UnicodeDecodeError: кодек "ascii" не може декодувати байт 0xd1 у позиції 2: порядковий не знаходиться в діапазоні (128)


107

Я намагаюся працювати з дуже великим набором даних, у якому є деякі нестандартні символи. Мені потрібно використовувати Unicode відповідно до специфікацій роботи, але я збита з пантелику. (І цілком можливо, це все роблять неправильно.)

Я відкриваю CSV за допомогою:

 15     ncesReader = csv.reader(open('geocoded_output.csv', 'rb'), delimiter='\t', quotechar='"')

Потім я намагаюся кодувати це за допомогою:

name=school_name.encode('utf-8'), street=row[9].encode('utf-8'), city=row[10].encode('utf-8'), state=row[11].encode('utf-8'), zip5=row[12], zip4=row[13],county=row[25].encode('utf-8'), lat=row[22], lng=row[23])

Я кодую все, крім lat та lng, оскільки їх потрібно надсилати в API. Коли я запускаю програму для розбору набору даних до того, що я можу використовувати, я отримую наступний Traceback.

Traceback (most recent call last):
  File "push_into_db.py", line 80, in <module>
    main()
  File "push_into_db.py", line 74, in main
    district_map = buildDistrictSchoolMap()
  File "push_into_db.py", line 32, in buildDistrictSchoolMap
    county=row[25].encode('utf-8'), lat=row[22], lng=row[23])
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128)

Я думаю, я повинен сказати вам, що я використовую python 2.7.2, і це частина побудови додатків на django 1.4. Я прочитав кілька публікацій на цю тему, але жодне з них, здається, не застосовується безпосередньо. Будь-яка допомога буде дуже вдячна.

Можливо, ви також хочете знати, що деякі з нестандартних символів, що викликають проблему, є Ñ і, можливо, É.


1
Яке кодування оригінального файлу? Я думаю, вам слід розшифрувати його відповідно до оригінального кодування, а потім перетворити на utf 8
xiao 啸

можливий дублікат Encoding дає кодек "ascii" не може кодувати символ ... порядковий не знаходиться в діапазоні (128) " [Ред .: і приблизно мільйон інших теж, я впевнений.]
Карл Кнечтел

Відповіді:


152

Unicode не дорівнює UTF-8. Останнє - лише кодування для першого.

Ви робите це неправильно. Ви читаєте кодовані UTF-8- дані, тому вам доведеться декодувати рядок, закодований UTF-8, у рядок unicode.

Так просто замінити .encodeз .decode, і він повинен працювати (якщо .csv є UTF-8 кодуванні).

Хоча нічого не соромно. Б'юсь об заклад, 3-х у 5 програмістів спочатку виникли проблеми, якщо не більше;)

Оновлення: Якщо ваші вхідні дані не закодовані UTF-8, то .decode(), звичайно , вам доведеться виконати відповідне кодування. Якщо нічого не дано, python передбачає ASCII, що, очевидно, виходить з ладу для не ASCII-символів.


1
Причиною помилки є те, що Python намагається автоматично розшифрувати його з кодування за замовчуванням, ASCII, щоб потім він міг кодувати його, як він вказав, до UTF-8. Оскільки дані недійсні ASCII, вони не працюють.
agf

7
звичайно, але якщо це дані, кодовані UTF8 (як я здогадуюсь), тоді .decode('utf-8')слід робити трюк, чи ні?
ch3ka

Звичайно, ти, мабуть, маєш рацію. Я просто пояснював, чому ви отримуєте таку конкретну помилку в цій ситуації.
agf

1
Ідеально! Велике спасибі. Отже, виявляється, що це був .decode ("латинський-1") - це має сенс, тому що саме Ñ це дало мені проблему. Знову! Дякую!
jelkimantis

Ваше рішення працює в деяких випадках, але у випадку, якщо я використовую це, я отримую ще одну помилку кодека "ascii" не може кодувати символ u '\ xf1' у позиції 2: порядковий не в діапазоні (128)
Вікаш Мішра

84

Просто додайте ці рядки до кодів:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

5
`AttributeError: модуль 'sys' не має атрибута 'setdefaultencoding', схоже, не працює в Python 3
skjerns

Вуто вуо! Це мені допомогло.
Shougo Makishima

1
Він працює для мого Python 2.7, зауважте, необхідне перезавантаження (sys), інакше setdefaultencoding не було б доступним.
Ю. Шень

1
Це було єдине, що змусило мене працювати з багатьох питань ТА. Дуже дякую!
Фредо

назва 'reload' не визначено
Davide

28

для користувачів Python 3. Ви можете зробити

with open(csv_name_here, 'r', encoding="utf-8") as f:
    #some codes

він працює і з колбою :)


1
Вперше я комусь тут допомогла. відчуває себе добре, знаючи, що я допоміг :)
Skrmnghrd

1
І ви мені також допомогли :) Усі інші відповіді не працювали для читання файлів. Тепер мені потрібно з’ясувати, як це виправити також для написання;)
user2194898

чи можете ви надіслати мені посилання вашого коду? Я спробую допомогти
Skrmnghrd

9

Основна причина помилки полягає в тому, що кодування за замовчуванням, яке передбачає python, це ASCII. Отже, якщо рядкові дані, encode('utf8')котрі повинні кодуватися, містять символи, що знаходяться поза діапазоном ASCII, наприклад для рядка типу "hgvcj 터 파크 387", python буде видавати помилку, оскільки рядок не в очікуваному форматі кодування.

Якщо ви використовуєте версію python раніше, ніж версія 3.5, надійним виправленням буде встановити кодування за замовчуванням, яке передбачає python utf8:

import sys
reload(sys)
sys.setdefaultencoding('utf8')
name = school_name.encode('utf8')

Таким чином python зможе передбачити символи в рядку, що виходить за межі діапазону ASCII.

Однак якщо ви використовуєте python версії 3.5 або вище, функція reload () недоступна, тому вам доведеться виправити її за допомогою декодування, наприклад

name = school_name.decode('utf8').encode('utf8')

яка різниця між вашою відповіддю та моєю
хелілі миліана

1
Більш детально. Люди часто вважають корисними відомості. І ваш код працює BTW, відхилення не передбачається.
Темі Факунле

1
перезавантаження доступне в Python 3, вам просто доведеться імпортувати його. from imp import reload
Meow

@Meow, але в Python 3. немає sys.setdefaultencoding. Тож у контексті сумісності py2 \ py3 буде перевірена деяка перевірка, можливо, sys.getdefaultencoding () можливо. Буду вдячний за пораду з цього приводу. stackoverflow.com/questions/28127513 / ...
Konst54

2

Для користувачів Python 3:

зміна кодування з 'ascii' на 'latin1' працює.

Крім того, ви можете спробувати знайти кодування автоматично, прочитавши топ-10000 байт за допомогою фрагмента нижче:

import chardet  
with open("dataset_path", 'rb') as rawdata:  
            result = chardet.detect(rawdata.read(10000))  
print(result)

2

На моєму комп’ютері встановлено неправильну локальну установку

Я вперше це зробив

>>> import locale
>>> locale.getpreferredencoding(False)
'ANSI_X3.4-1968'

locale.getpreferredencoding(False)це функція, яку викликає, open()коли ви не надаєте кодування . Вихід повинен бути 'UTF-8', але в цьому випадку це якийсь варіант ASCII .

Потім я запустив команду bash localeі отримав цей вихід

$ locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

Отже, я використовував локальну локальну систему Ubuntu, яка змушує Python відкривати файли як ASCII замість UTF-8. Я повинен був встановити свій мовний стандарт дляen_US.UTF-8

sudo apt install locales 
sudo locale-gen en_US en_US.UTF-8    
sudo dpkg-reconfigure locales

Якщо ви не можете змінити локальну систему в цілому, ви можете викликати весь ваш код Python таким чином:

PYTHONIOENCODING="UTF-8" python3 ./path/to/your/script.py

або робити

export PYTHONIOENCODING="UTF-8"

щоб встановити його в оболонці, яку ви запускаєте.


1

якщо ви отримаєте цю проблему під час роботи certbot під час створення або поновлення сертифіката, будь ласка, використовуйте наступний метод

grep -r -P '[^\x00-\x7f]' /etc/apache2 /etc/letsencrypt /etc/nginx

Ця команда знайшла ображаючий символ "´" в одному файлі .conf у коментарі. Після видалення (ви можете редагувати коментарі за своїм бажанням) та перезавантажити nginx, все працювало заново.

Джерело: https://github.com/certbot/certbot/isissue/5236


0

Або коли ви маєте справу з текстом на Python, якщо це текст Unicode, зробіть примітку, що це Unicode.

Встановити text=u'unicode text'замість просто text='unicode text'.

Це спрацювало в моєму випадку.


0

відкрити кодуванням UTF 16 через ширину та довгу.

with open(csv_name_here, 'r', encoding="utf-16") as f:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.