Помилка кодування Python Unicode


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 під час читання?


Я щойно приїжджав до ТА, щоб поставити це питання. Чи існує простий спосіб очистити струну 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, проблема, ймовірно, раніше. Спробуйте скористатися цим кодом: # - - кодування: latin-1 - - u = u 'foo «смуга смуги» df' print u.encode ('ascii', 'ignore') Для вас, ймовірно, було перетворено ваш рядок в UNICode, заданий кодування, яке ви вказали для сценарію python, який викинув помилку.
Скотт Стаффорд

Я пішов уперед і перетворив свою проблему на власне питання: stackoverflow.com/questions/3224427/…
Нік Хайнер

1
.encode('ascii', 'ignore')без необхідності втрачає дані, навіть якщо середовище ОП може підтримувати символи, які не мають права (більшість випадків)
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
Це не допомагає у питанні ОП: "не можна кодувати символ 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 .


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 \ текст будується на str ... та піддисципліни Computer Engineering \ u2019s. ']) Рядок знаходиться в UTF-8 як ви можете бачити, але це озлобилося на внутрішній '\ u2019'
Алекс Б

О, гаразд, я думав, у вас виникають інші проблеми.
David Z

7
@ Алекс В: Ні, рядок є Unicode, а не Utf-8. Щоб кодувати його як Utf-8, використовуйте'...'.encode('utf-8')
sth

0

Я написав наступне, щоб виправити неприємні котирування, які не мають права, і перетворити силу на щось корисне.

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

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 , і може врятувати вас від зайвого головного болю, якщо точність символів не є тим, за чим ви хочете, але все ж хочете мати читабельність людини.

Віраван


-1

Спробуйте додати наступний рядок у верхній частині сценарію python.

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

-1

Пітон 3.5, 2018

Якщо ви не знаєте, що таке кодування, але у аналізатора Unicode виникають проблеми, ви можете відкрити файл у Notepad++верхній смузі та вибрати вгорі Encoding->Convert to ANSI. Тоді ви можете написати свій пітон так

with open('filepath', 'r', encoding='ANSI') as file:
    for word in file.read().split():
        print(word)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.