В производственной системе возникает ошибка, которую не удается воспроизвести в среде разработки:

with io.open(file_name, 'wt') as fd:
    fd.write(data)

Исключение:

  File "/home/.../foo.py", line 18, in foo
    fd.write(data)

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 6400: ordinal not in range(128)

Я уже пытался добавить много странных символов в переменную data.

Но до сих пор я не мог воспроизвести UnicodeEncodeError.

Что должно быть в data, чтобы получить UnicodeEncodeError?

Обновить

python -c 'import locale; print locale.getpreferredencoding()'
UTF-8

Update2

Если я вызываю locale.getpreferredencoding() через оболочку и через веб-запрос, кодировка «UTF-8».

Я обновил обработку исключений в своем коде и регистрирую getpreferredencoding() с некоторых дней. Теперь это случилось снова (до сих пор я не могу заставить или воспроизвести это), и кодировка "ANSI_X3.4-1968"!

Я понятия не имею, где эта кодировка устанавливается ....

Это ставит мою проблему в другом направлении. Оставлять этот вопрос бесполезным. Моя проблема сейчас: где изменяется предпочтительная кодировка? Но это не часть этого вопроса.

Большое спасибо всем, кто

6
guettli 10 Янв 2017 в 14:48

3 ответа

Лучший ответ

Вы полагаетесь на кодировку по умолчанию для платформы; когда эта кодировка по умолчанию не может поддерживать символы Unicode, которые вы пишете в файл, вы получаете исключение кодировки.

Из io.open() документации:

encoding - это имя кодировки, используемой для декодирования или кодирования файла. Это следует использовать только в текстовом режиме. Кодировка по умолчанию зависит от платформы ( locale.getpreferredencoding() возвращает), но может использоваться любая кодировка, поддерживаемая Python.

В вашей конкретной ситуации по умолчанию, возвращаемое locale.getpreferredencoding(), является ASCII, поэтому любой символ Unicode вне диапазона ASCII может вызвать эту проблему, U-0080 и выше.

Обратите внимание, что локаль берется из вашей среды; если это ASCII, это обычно означает, что языковой стандарт установлен в Язык POSIX по умолчанию, C.

Укажите кодировку явно:

with io.open(file_name, 'wt', encoding='utf8') as fd:
    fd.write(data)

Я использовал UTF-8 в качестве примера; то, что вы выбираете, полностью зависит от ваших вариантов использования и данных, которые вы пытаетесь записать.

7
Martijn Pieters 18 Янв 2017 в 16:21

Оберните ваш write в try / except и сохраните данные в двоичный файл - вы сможете точно увидеть, какие данные вызывают у вас проблемы:

with io.open(file_name, 'wt') as fd:
    try:
        fd.write(data)
    except UnicodeEncodeError:
        with open('/path/to/save/error.bin', 'wb') as err:
            err.write(data)
        raise
0
Ethan Furman 13 Янв 2017 в 21:41

Я попытался это воспроизвести ошибку:

with open(filename, 'wt', encoding='ascii') as fd:
    fd.write('\xa0')

Traceback (последний вызов был последним):
Файл "test.py", строка 2, в fd.write ( ' \ xa0 ')
UnicodeEncodeError: кодек «ascii» не может кодировать символ «\ xa0» в позиции 0: порядковый номер не в диапазоне (128)

1
Juggernaut 16 Янв 2017 в 00:45