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 ]

13 голосов
/ 26 сентября 2017

Вот перефразировка некоторых других так называемых «отписанных» ответов.Существуют ситуации, в которых простое выбрасывание проблемных символов / строк является хорошим решением, несмотря на протесты, озвученные здесь.

def safeStr(obj):
    try: return str(obj)
    except UnicodeEncodeError:
        return obj.encode('ascii', 'ignore').decode('ascii')
    except: return ""

Тестирование:

if __name__ == '__main__': 
    print safeStr( 1 ) 
    print safeStr( "test" ) 
    print u'98\xb0'
    print safeStr( u'98\xb0' )

Результаты:

1
test
98°
98

Предложение: вы могли бы вместо этого присвоить этой функции toAscii?Это вопрос предпочтений.

Это было написано для Python 2. Для Python 3, я думаю, вы захотите использовать bytes(obj,"ascii") вместо str(obj).Я еще не проверял это, но в какой-то момент я уточню ответ.

10 голосов
/ 30 января 2019

В оболочке:

  1. Найти поддерживаемый языковой стандарт UTF-8 с помощью следующей команды:

    locale -a | grep "UTF-8"
    
  2. Экспортируйте его перед запускомскрипт, например:

    export LC_ALL=$(locale -a | grep UTF-8)
    

    или вручную, например:

    export LC_ALL=C.UTF-8
    
  3. Проверьте его, напечатав специальный символ, например, :

    python -c 'print(u"\u2122");'
    

Выше проверено в Ubuntu.

8 голосов
/ 27 февраля 2018

Я всегда помещаю приведенный ниже код в первые две строки файлов python:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
6 голосов
/ 31 декабря 2015

Найдены простые вспомогательные функции здесь .

def safe_unicode(obj, *args):
    """ return the unicode representation of obj """
    try:
        return unicode(obj, *args)
    except UnicodeDecodeError:
        # obj is byte string
        ascii_text = str(obj).encode('string_escape')
        return unicode(ascii_text)

def safe_str(obj):
    """ return the byte string representation of obj """
    try:
        return str(obj)
    except UnicodeEncodeError:
        # obj is unicode
        return unicode(obj).encode('unicode_escape')
4 голосов
/ 31 января 2018

Просто добавьте в переменную encode ('utf-8')

agent_contact.encode('utf-8')
3 голосов
/ 28 ноября 2016

Я просто использовал следующее:

import unicodedata
message = unicodedata.normalize("NFKD", message)

Проверьте, что об этом говорится в документации:

unicodedata.normalize (form, unistr) Возвращает форму обычной формы для Unicodeструнный юнистр.Допустимыми значениями для формы являются «NFC», «NFKC», «NFD» и «NFKD».

Стандарт Unicode определяет различные формы нормализации строки Unicode на основе определения канонической эквивалентности и эквивалентности совместимости.,В Unicode несколько символов могут быть выражены по-разному.Например, символ U + 00C7 (LATIN CAPITAL LETTER C с CEDILLA) также может быть выражен в виде последовательности U + 0043 (LATIN CAPITAL LETTER C) U + 0327 (COMBINING CEDILLA).

Для каждого символа:Есть две нормальные формы: нормальная форма C и нормальная форма D. Нормальная форма D (NFD) также известна как каноническое разложение и переводит каждый символ в его разложенную форму.Нормальная форма C (NFC) сначала применяет каноническую декомпозицию, затем снова создает предварительно объединенные символы.

В дополнение к этим двум формам существуют две дополнительные нормальные формы, основанные на эквивалентности совместимости.В Unicode поддерживаются определенные символы, которые обычно объединяются с другими символами.Например, U + 2160 (ROMAN NUMERAL ONE) действительно то же самое, что U + 0049 (LATIN CAPITAL LETTER I).Однако он поддерживается в Юникоде для совместимости с существующими наборами символов (например, gb2312).

Нормальная форма KD (NFKD) будет применять декомпозицию совместимости, то есть заменять все символы совместимости их эквивалентами.Нормальная форма KC (NFKC) сначала применяет декомпозицию совместимости, а затем каноническую композицию.

Даже если две строки Unicode нормализованы и выглядят одинаково для читателя-человека, если одна имеет комбинированные символы, а другая - нет.т, они могут не сравниваться равными.

Решает это для меня.Просто и легко.

3 голосов
/ 02 ноября 2017

Ниже решение сработало для меня, просто добавил

u "String"

(представляющий строку как Unicode) перед моей строкой.

3 голосов
/ 24 апреля 2019

Это помогает в python 2.7

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

Это помогает повторно включить sys.setdefaultencoding ()

2 голосов
/ 25 декабря 2018

Пожалуйста, откройте терминал и выполните следующую команду:

export LC_ALL="en_US.UTF-8"
2 голосов
/ 11 апреля 2018

Мы столкнулись с этой ошибкой при запуске manage.py migrate в Django с локализованными приспособлениями.

Наш источник содержал объявление # -*- coding: utf-8 -*-, MySQL был правильно настроен для utf8, а Ubuntu имел соответствующий языковой пакет и значения в /etc/default/locale.

Проблема заключалась в том, что в контейнере Django (мы используем docker) отсутствовал LANG env var.

Установка LANG в en_US.UTF-8 и перезапуск контейнера передповторное выполнение миграций решило проблему.

...