Почему я получаю ошибку кодирования в python warnings.formatwarning для строки формата? - PullRequest
5 голосов
/ 06 октября 2009

Я получаю ошибку кодирования в этой строке:

s =  "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)

UnicodeEncodeError: кодек 'ascii' не может кодировать символ u '\ xc4' в позиции 44: порядковый номер не в диапазоне (128)

Я попытался воспроизвести эту ошибку, передав все комбинации параметров в строковый формат, но наиболее близкой я получил ошибку «ascii decode» (при одновременной передаче unicode и high ascii string, что привело к преобразованию строки в unicode с использованием ascii декодера .

Однако мне не удалось получить ошибку "ascii encode". У кого-нибудь есть идея?

Ответы [ 3 ]

8 голосов
/ 06 октября 2009

Это происходит, когда Python пытается привести аргумент:

s = u"\u00fc"
print str(s)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 0: ordinal not in range(128)

Это происходит потому, что один из ваших аргументов является объектом (не какой-либо строкой), и Python вызывает str() для него. Есть два решения: использовать строку формата Юникод для формата (s = u"%s...") или заключить каждый аргумент в repr().

8 голосов
/ 06 октября 2009

Вы смешиваете юникод и str объекты.

Пояснение: В Python 2.x есть два вида объектов, которые могут содержать текстовые строки. ул и юникод. str - это строка байтов, поэтому она может содержать только символы от 0 до 255. Юникод - это строка символов Юникода.

Вы можете конвертировать между str и unicode с помощью методов «encode» и «decode»:

>>> "thisisastring".decode('ascii')
u'thisisastring'

>>> u"This is ä string".encode('utf8')    
'This is \xc3\xa4 string'

Обратите внимание на кодировки. Кодировки - это способы представления текста Unicode в виде только строк байтов.

Если вы попытаетесь добавить str и unicode вместе, Python попытается преобразовать одно в другое. Но по умолчанию он будет использовать ASCII в качестве кодировки, что означает a-z, A-Z и некоторые дополнительные символы, такие как !"#$%&/()=?'{[]]} и т. Д. В противном случае произойдет сбой.

В этот момент вы получите либо ошибку кодирования, либо ошибку декодирования, в зависимости от того, попытается ли Python преобразовать юникод в str или str в юникод. Обычно он пытается декодировать, то есть конвертировать в юникод. Но иногда он решает не принуждать, а натягивать. Я не совсем уверен, почему.

Обновление: Причина, по которой вы получаете ошибку кодирования, а не ошибку декодирования, указанную выше, заключается в том, что message в приведенном выше коде не является ни str, ни unicode. Это еще один объект, у которого есть метод str . Поэтому Python перед отправкой отправляет str (message), и это не удается, поскольку внутренне хранимое сообщение является объектом Unicode, который не может быть приведен к ascii.

Или, проще говоря: он не работает, так как warnings.warn () не принимает сообщения Unicode.

Теперь решение:

Не смешивайте str и unicode. Если вам нужно использовать Unicode, и вы, очевидно, делаете, постарайтесь, чтобы все строки были Unicode все время. Это единственный способ убедиться, что вы избежите этого. Это означает, что всякий раз, когда вы читаете строку с диска или вызываете функцию, которая может возвратить что-либо, кроме чистой ascii str, декодируйте ее как можно быстрее в unicode. А когда вам нужно сохранить его на диск или отправить по сети или передать его методу, который не понимает Unicode, закодируйте его в str как можно позже.

В данном конкретном случае проблема заключается в том, что вы передаете unicode в warnings.warn (), и вы не можете этого сделать. Передайте строку. Если вы не знаете, что это такое (как, кажется, имеет место здесь), потому что это происходит откуда-то еще, ваши решения try / кроме с repr работают нормально, хотя было бы возможным выполнить кодирование.

1 голос
/ 06 октября 2009

Один из передаваемых вами операндов не подходит для кодирования ASCII - возможно, он содержит символы Unicode или Latin-1. Измените строку формата на Unicode и посмотрите, что произойдет.

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