Ошибка кодирования Unicode Python

104

Я читаю и разбираю XML-файл Amazon, и, хотя в XML-файле отображается ', при попытке его распечатать я получаю следующую ошибку:

'ascii' codec can't encode character u'\u2019' in position 16: ordinal not in range(128) 

Из того, что я читал в Интернете, ошибка возникает из-за того, что XML-файл находится в UTF-8, но Python хочет обрабатывать его как символ в кодировке ASCII. Есть ли простой способ избавиться от ошибки и заставить мою программу печатать XML по мере чтения?

Алекс Б
источник
Я просто приехал в SO, чтобы опубликовать этот вопрос. Есть ли простой способ дезинфицировать строку unicode()?
Ник Хайнер,
Пожалуйста, проверьте также этот ответ на связанный вопрос: «Python UnicodeDecodeError - я неправильно понимаю кодировку?»
tzot

Ответы:

193

Вероятно, ваша проблема в том, что вы правильно его проанализировали, и теперь вы пытаетесь распечатать содержимое XML и не можете, потому что есть некоторые иностранные символы Unicode. Попробуйте сначала закодировать вашу строку Unicode как ascii:

unicodeData.encode('ascii', 'ignore')

часть «игнорировать» скажет ему просто пропустить эти символы. Из документов python:

>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'&#40960;abcd&#1972;'

Возможно, вы захотите прочитать эту статью: http://www.joelonsoftware.com/articles/Unicode.html , которую я нашел очень полезной в качестве базового руководства по происходящему. После прочтения вы перестанете чувствовать, что просто гадаете, какие команды использовать (или, по крайней мере, это случилось со мной).

Скотт Стаффорд
источник
1
Я пытаюсь обезопасить следующую строку: 'foo «bar bar» df' (обратите внимание на фигурные кавычки), но вышесказанное мне все равно не удается.
Ник Хайнер,
@Rosarch: Как это не удается? та же ошибка? И какое правило обработки ошибок вы использовали?
Скотт Стаффорд
@Rosarch, у тебя проблема, наверное, раньше. Попробуйте этот код: # - - coding: latin-1 - - u = u 'foo «bar bar» df' print u.encode ('ascii', 'ignore') Для вас, вероятно, это было преобразование вашей строки в данный юникод кодировка, которую вы указали для скрипта python, вызвавшего ошибку.
Скотт Стаффорд
Я пошел дальше и сформулировал свою проблему в отдельном вопросе: stackoverflow.com/questions/3224427/…
Ник Хайнер,
1
.encode('ascii', 'ignore')теряет данные без необходимости, даже если среда OP может поддерживать символы, отличные от ascii (в большинстве случаев)
jfs
16

Лучшее решение:

if type(value) == str:
    # Ignore errors even if the string is not proper UTF-8 or has
    # broken marker bytes.
    # Python built-in function unicode() can do this.
    value = unicode(value, "utf-8", errors="ignore")
else:
    # Assume the value object has proper __unicode__() method
    value = unicode(value)

Если вы хотите узнать больше о том, почему:

http://docs.plone.org/manage/troubleshooting/unicode.html#id1

Паксвелл
источник
3
Это не помогает с проблемой OP: «не удается закодировать символ u '\ u2019'» . u'\u2019уже Unicode.
jfs
6

Не кодируйте кодировку символов вашего окружения внутри скрипта; вместо этого напечатайте текст Unicode напрямую:

assert isinstance(text, unicode) # or str on Python 3
print(text)

Если ваш вывод перенаправлен в файл (или канал); вы можете использовать PYTHONIOENCODINGenvvar, чтобы указать кодировку символов:

$ PYTHONIOENCODING=utf-8 python your_script.py >output.utf8

В противном случае, python your_script.pyдолжен работать как - ваши региональные настройки используются для кодирования текста (на проверки POSIX: LC_ALL, LC_CTYPE, LANGenvvars - наборLANG в кодировке UTF-8 локали , если это необходимо).

Чтобы распечатать Unicode в Windows, см. Этот ответ, в котором показано, как распечатать Unicode в консоли Windows, в файл или с помощью IDLE .

jfs
источник
1

Отличный пост: http://www.carlosble.com/2010/12/understanding-python-and-unicode/

# -*- coding: utf-8 -*-

def __if_number_get_string(number):
    converted_str = number
    if isinstance(number, int) or \
            isinstance(number, float):
        converted_str = str(number)
    return converted_str


def get_unicode(strOrUnicode, encoding='utf-8'):
    strOrUnicode = __if_number_get_string(strOrUnicode)
    if isinstance(strOrUnicode, unicode):
        return strOrUnicode
    return unicode(strOrUnicode, encoding, errors='ignore')


def get_string(strOrUnicode, encoding='utf-8'):
    strOrUnicode = __if_number_get_string(strOrUnicode)
    if isinstance(strOrUnicode, unicode):
        return strOrUnicode.encode(encoding)
    return strOrUnicode
Ранвиджай Сачан
источник
0

Вы можете использовать что-нибудь в форме

s.decode('utf-8')

который преобразует байтовую строку в кодировке UTF-8 в строку Python Unicode. Но точная процедура, которую следует использовать, зависит от того, как именно вы загружаете и анализируете XML-файл, например, если вы никогда не обращаетесь к XML-строке напрямую, вам, возможно, придется использовать объект декодера из codecsмодуля .

Дэвид З
источник
Он уже закодирован в UTF-8. В частности, ошибка: myStrings = deque ([текст u'Dorf и Svoboda \ u2019s основан на поддисциплинах str ... и Computer Engineering \ u2019s. ']) Строка находится в UTF-8 как вы можете видеть, но он злится на внутреннее '\ u2019'
Alex B
О, хорошо, я думал, у тебя другая проблема.
David Z
7
@Alex B: Нет, это Unicode, а не Utf-8. Чтобы закодировать его как Utf-8, используйте'...'.encode('utf-8')
sth
0

Я написал следующее, чтобы исправить неприятные кавычки, отличные от ascii, и принудительно преобразовать их во что-то пригодное для использования.

unicodeToAsciiMap = {u'\u2019':"'", u'\u2018':"`", }

def unicodeToAscii(inStr):
    try:
        return str(inStr)
    except:
        pass
    outStr = ""
    for i in inStr:
        try:
            outStr = outStr + str(i)
        except:
            if unicodeToAsciiMap.has_key(i):
                outStr = outStr + unicodeToAsciiMap[i]
            else:
                try:
                    print "unicodeToAscii: add to map:", i, repr(i), "(encoded as _)"
                except:
                    print "unicodeToAscii: unknown code (encoded as _)", repr(i)
                outStr = outStr + "_"
    return outStr
user5910
источник
0

Если вам нужно вывести на экран приблизительное представление строки, а не игнорировать эти непечатаемые символы, попробуйте unidecode пакет здесь:

https://pypi.python.org/pypi/Unidecode

Объяснение находится здесь:

https://www.tablix.org/~avian/blog/archives/2009/01/unicode_transliteration_in_python/

Это лучше, чем использовать u.encode('ascii', 'ignore')для данной строкиu , и может избавить вас от ненужной головной боли, если точность символа не то, что вам нужно, но все же нужно, чтобы человек читал.

Wirawan

Вираван Пурванто
источник
-1

Попробуйте добавить следующую строку вверху вашего скрипта python.

# _*_ coding:utf-8 _*_
Abnvanand
источник
-1

Python 3.5, 2018 г.

Если вы не знаете, какая кодировка, но у парсера юникода возникают проблемы, вы можете открыть файл Notepad++и выбрать в верхней панели Encoding->Convert to ANSI. Затем вы можете написать свой питон следующим образом

with open('filepath', 'r', encoding='ANSI') as file:
    for word in file.read().split():
        print(word)
Атомар94
источник