Как напечатать список строк, если я не могу заранее знать кодировку символов? - PullRequest
1 голос
/ 06 сентября 2010

Я получаю список имен из веб-службы, используя клиент, написанный на Python.Получив список, я кодирую каждое имя в Unicode, а затем печатаю каждое из них в стандартный вывод.Когда я получаю имя «Олафур Йохан Олафссон», я получаю следующую ошибку:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
                    ordinal not in range(128)

Поскольку я не могу знать, какой будет кодировка, как мне преобразовать все эти строки в Unicode?Или вы можете предложить лучший способ решения этой проблемы?

Ответы [ 3 ]

1 голос
/ 07 сентября 2010

Эта страница может вам помочь http://wiki.python.org/moin/PrintFails

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

1 голос
/ 07 сентября 2010

Прежде всего, вы декодируете данные в Unicode ( отсутствие кодирования) при чтении из файла, канала, сокета, терминала и т. Д .; и кодировать Unicode в соответствующую байтовую кодировку при отправке / сохранении данных. Я подозреваю, что это корень вашей проблемы.

Веб-сервис должен объявить кодировку в заголовках или полученных данных. print обычно автоматически кодирует Unicode в кодировку терминала (обнаруживается через sys.stdout.encoding) или при отсутствии этого просто ascii. Если символы в ваших данных не поддерживаются целевой кодировкой, вы получите UnicodeEncodeError.

Поскольку это не та ошибка, которую вы получили, вы должны опубликовать некоторый код, чтобы мы могли видеть, что вы делаете. Скорее всего, вы кодируете байтовую строку вместо декодируете . Вот пример этого:

>>> data = '\xc2\xbd' # UTF-8 encoded 1/2 symbol.
>>> data.encode('cp437')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\dev\python\lib\encodings\cp437.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_map)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)

То, что я сделал здесь, это вызов encode в байтовой строке. Поскольку encode требуется строка Unicode, Python использовал кодировку по умолчанию ascii для декодирования строки байта в Unicode, а затем для кодирования в cp437.

Исправьте это путем декодирования вместо кодирования данных, тогда print будет автоматически кодировать в стандартный вывод. Пока ваш терминал поддерживает символы в данных, он будет отображаться правильно:

>>> import sys
>>> sys.stdout.encoding
'cp437'
>>> print data.decode('utf8') # implicit encode to sys.stdout.encoding
½
>>> print data.decode('utf8').encode('cp437') # explicit encode.
½
1 голос
/ 06 сентября 2010

Модуль UnicodeDammit из BeautifulSoup может автоматически определять кодировку.

from BeautifulSoup import UnicodeDammit

u = UnicodeDammit("Ólafur Jóhann Ólafsson")

print u.unicode
print u.originalEncoding
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...