UnicodeEncodeError: кодек 'ascii' не может кодировать символ u '\ xa0' в позиции 20: порядковый номер не в диапазоне (128) - PullRequest
1164 голосов
/ 30 марта 2012

У меня проблемы с работой символов юникода из текста, полученного с разных веб-страниц (на разных сайтах). Я использую BeautifulSoup.

Проблема в том, что ошибка не всегда воспроизводима; иногда он работает с некоторыми страницами, а иногда он бросает UnicodeEncodeError. Я перепробовал практически все, что мог придумать, и все же я не нашел ничего, что работало бы последовательно, не выдавая какую-то ошибку, связанную с Unicode.

Один из разделов кода, который вызывает проблемы, показан ниже:

agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()

Вот трассировка стека, созданная для НЕКОТОРЫХ строк при выполнении приведенного выше фрагмента:

Traceback (most recent call last):
  File "foobar.py", line 792, in <module>
    p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)

Я подозреваю, что это связано с тем, что некоторые страницы (или, в частности, страницы с некоторых сайтов) могут быть закодированы, а другие могут быть не закодированы. Все сайты базируются в Великобритании и предоставляют данные, предназначенные для потребления в Великобритании - поэтому нет проблем, связанных с интернализацией или работой с текстом, написанным на чем-либо, кроме английского.

У кого-нибудь есть идеи, как решить эту проблему, чтобы я ПОСТОЯННО исправил эту проблему?

Ответы [ 27 ]

1250 голосов
/ 30 марта 2012

Вам нужно прочитать Python Unicode HOWTO .Эта ошибка - самый первый пример .

По сути, прекратите использовать str для преобразования из Unicode в закодированный текст / байты.

Вместо этого правильно используйте .encode() для кодирования строки:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

или работа полностью в Unicode.

410 голосов
/ 30 марта 2012

Это классическая болевая точка Python Unicode!Рассмотрим следующее:

a = u'bats\u00E0'
print a
 => batsà

Пока все хорошо, но если мы вызовем str (a), давайте посмотрим, что произойдет:

str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

О, провал, это никому не подойдетхорошо!Чтобы исправить ошибку, закодируйте байты явно с помощью .encode и сообщите python, какой кодек использовать:

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

Voil \ u00E0!

Проблема заключается в том, что при вызове str (),Python использует кодировку символов по умолчанию, чтобы попытаться закодировать байты, которые вы ей дали, которые в вашем случае иногда являются представлениями символов Юникода.Чтобы решить эту проблему, вы должны указать python, как обращаться со строкой, которую вы ей передаете, используя .encode ('what_unicode').Большую часть времени у вас должно быть все в порядке, используя utf-8.

Отличное изложение этой темы см. В выступлении Неда Батчелдера на PyCon здесь: http://nedbatchelder.com/text/unipain.html

196 голосов
/ 20 августа 2014

Я нашел изящную работу для удаления символов и продолжения сохранения строки в виде строки следующим образом:

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

Важно отметить, что использование параметра игнорирования является опасным , посколькуон молча отбрасывает любую поддержку юникода (и интернационализации) из кода, который его использует, как показано здесь (конвертировать юникод):

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'
139 голосов
/ 02 сентября 2016

хорошо, я попробовал все, но это не помогло, после поиска в Google я понял следующее, и это помогло. Python 2.7 используется.

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
80 голосов
/ 02 декабря 2013

Тонкая проблема, приводящая к сбою даже печати, заключается в неправильной установке переменных среды, например.здесь LC_ALL установлен в "C".В Debian не рекомендуется устанавливать его: Вики Debian на языке

$ echo $LANG
en_US.utf8
$ echo $LC_ALL 
C
$ python -c "print (u'voil\u00e0')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil\u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil\u00e0')"
voilà
26 голосов
/ 26 января 2015

Для меня то, что сработало, было:

BeautifulSoup(html_text,from_encoding="utf-8")

Надеюсь, это кому-нибудь поможет.

25 голосов
/ 01 ноября 2013

Я на самом деле обнаружил, что в большинстве моих случаев просто вырезать эти символы намного проще:

s = mystring.decode('ascii', 'ignore')
20 голосов
/ 23 июня 2018

Попробуйте это может решить,

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
19 голосов
/ 13 августа 2015

Проблема в том, что вы пытаетесь напечатать символ Unicode, но ваш терминал не поддерживает его.

Вы можете попробовать установить пакет language-pack-en, чтобы исправить это:

sudo apt-get install language-pack-en

, который предоставляет обновления данных перевода на английский язык для всех поддерживаемых пакетов (включая Python). При необходимости установите другой языковой пакет (в зависимости от того, какие символы вы пытаетесь напечатать).

В некоторых дистрибутивах Linux это необходимо для того, чтобы убедиться, что английские локали по умолчанию настроены правильно (чтобы символы юникода могли обрабатываться оболочкой / терминалом). Иногда его проще установить, чем настроить вручную.

Затем при написании кода убедитесь, что вы используете правильную кодировку в вашем коде.

Например:

open(foo, encoding='utf-8')

Если проблема не устранена, дважды проверьте конфигурацию вашей системы, например:

  • Ваш файл локали (/etc/default/locale), который должен иметь, например,

    LANG="en_US.UTF-8"
    LC_ALL="en_US.UTF-8"
    

    или

    LC_ALL=C.UTF-8
    LANG=C.UTF-8
    
  • Значение LANG / LC_CTYPE в оболочке.

  • Проверьте, какая локаль поддерживает ваша оболочка:

    locale -a | grep "UTF-8"
    

Демонстрация проблемы и решения в новой виртуальной машине.

  1. Инициализация и подготовка виртуальной машины (например, с использованием vagrant):

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
    

    См .: доступные ящики Ubuntu . .

  2. Печать символов Unicode (например, знака торговой марки, например ):

    $ python -c 'print(u"\u2122");'
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
    
  3. Сейчас устанавливается language-pack-en:

    $ sudo apt-get -y install language-pack-en
    The following extra packages will be installed:
      language-pack-en-base
    Generating locales...
      en_GB.UTF-8... /usr/sbin/locale-gen: done
    Generation complete.
    
  4. Теперь проблема должна быть решена:

    $ python -c 'print(u"\u2122");'
    ™
    
  5. В противном случае попробуйте следующую команду:

    $ LC_ALL=C.UTF-8 python -c 'print(u"\u2122");'
    ™
    
16 голосов
/ 08 августа 2016

Добавьте строку ниже в начале вашего скрипта (или как вторую строку):

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

Это определение кодировки исходного кода Python. Больше информации в PEP 263 .

...