Почему бы нам не использовать sys.setdefaultencoding ("utf-8") в скрипте py?



Я видел несколько скриптов py, которые используют это в верхней части скрипта. В каких случаях следует использовать?



import sys
reload(sys)
sys.setdefaultencoding("utf-8")
723   4  

4 ответов:

согласно документации: это позволяет переключаться с ASCII по умолчанию на другие кодировки, такие как UTF-8, которые среда выполнения Python будет использовать всякий раз, когда ей нужно декодировать строковый буфер в unicode.

эта функция доступна только во время запуска Python, когда Python сканирует среду. Он должен быть вызван в общесистемном модуле,sitecustomize.py, после того, как этот модуль был оценен,setdefaultencoding() функция удаляется из sys модуль.

только способ фактически использовать его - это перезагрузить хак,который возвращает атрибут.

и использование sys.setdefaultencoding() всегда был обескуражен, и он стал no-op в py3k. кодировка py3k жестко связана с "utf-8", и ее изменение вызывает ошибку.

Я предлагаю несколько советов для чтение:

tl; dr

ответ никогда! (если вы действительно не знаете, что делаете)

9/10 раз решение может быть решена с надлежащим пониманием кодирования / декодирования.

1/10 люди имеют неверно определенный язык или среду и должны установить:

PYTHONIOENCODING="UTF-8"  

в их среде, чтобы исправить проблемы печати консоли.

что это делать?

sys.setdefaultencoding("utf-8") (вычеркнуто, чтобы избежать повторного использования) изменяет кодировку/декодирование по умолчанию, используемое всякий раз, когда Python 2.x необходимо преобразовать Unicode () в str () (и наоборот), и кодировка не задана. Т. е.:

str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC") 

В Python 2.x, кодировка по умолчанию установлена в ASCII, и вышеприведенные примеры завершатся с ошибкой:

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

(моя консоль настроена как UTF-8, так что "€" = '\xe2\x82\xac', следовательно, исключение \xe2)

или

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

sys.setdefaultencoding("utf-8") позволит им работать для меня, но не обязательно будет работать для людей, которые не используют UTF-8. значение по умолчанию ASCII гарантирует, что предположения кодирования не запекаются в код

консоль

sys.setdefaultencoding("utf-8") также имеет побочный эффект, появляющийся исправить sys.stdout.encoding, используется при печати символов на консоль. Python использует пользователя языковой стандарт (Linux / OS X / Un*x) или кодовая страница (Windows), чтобы установить это. Иногда локаль пользователя нарушается и просто требует PYTHONIOENCODING исправить кодировка консоли.

пример:

$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()

$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€

что так плохо с sys.setdefaultencoding ("utf-8")?

люди разрабатывали против Python 2.x в течение 16 лет при том понимании, что кодировка по умолчанию-ASCII. UnicodeError методы обработки исключений были записаны в обрабатывать преобразования строк в Юникод для строк, которые содержат не ASCII.

от https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/

def welcome_message(byte_string):
    try:
        return u"%s runs your business" % byte_string
    except UnicodeError:
        return u"%s runs your business" % unicode(byte_string,
            encoding=detect_encoding(byte_string))

print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))

перед установкой defaultencoding этот код не сможет декодировать " Å " в кодировке ascii, а затем войдет в обработчик исключений, чтобы угадать кодировку и правильно превратить ее в unicode. Печать: Angstrom (Å®) запускает ваш бизнес. Как только вы установите defaultencoding в utf-8, код обнаружит, что byte_string можно интерпретировать как utf-8, и поэтому он будет искажать данные и возвращать их вместо этого: Angstrom (Ů) запускает ваш бизнес.

изменение того, что должно быть константой, будет иметь драматические последствия для модулей, от которых вы зависите. Лучше всего фиксировать данные в ваш код.

пример проблемы

при установке defaultencoding в UTF-8 не является основной причиной в следующем примере показано, как маскируются проблемы и как при изменении входной кодировки код разбивается неочевидным образом: UnicodeDecodeError: кодек 'utf8' не может декодировать байт 0x80 в позиции 3131: недопустимый начальный байт

#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u

chmod +x test.py
./test.py
moçambique
moçambique

./test.py > output.txt
Traceback (most recent call last):
  File "./test.py", line 5, in <module>
    print u
UnicodeEncodeError: 'ascii' codec can't encode character 
u'\xe7' in position 2: ordinal not in range(128)

на оболочке работает, отправка в sdtout нет , так что это один обходной путь, чтобы написать в stdout .

Я сделал другой подход, который не запускается, если sys.стандартный вывод.кодирование не определяется , или другими словами, сначала нужно экспортировать PYTHONIOENCODING=UTF-8 для записи в stdout.

import sys
if (sys.stdout.encoding is None):            
    print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout." 
    exit(1)


Итак, используя тот же пример:

export PYTHONIOENCODING=UTF-8
./test.py > output.txt

совместимость

  • первая опасность заключается в reload(sys).

    когда вы перезагружаете модуль, вы на самом деле получаете два копии модуля во время выполнения. Старый модуль является объектом Python, как и все остальное, и остается живым, пока есть ссылки на него. Итак,половина объектов будет указывать на старый модуль, а половина на новый. когда вы делаете некоторые изменения, вы никогда не увидите его ближайшие, когда какой-то случайный объект не видит изменения:

    (This is IPython shell)
    
    In [1]: import sys
    
    In [2]: sys.stdout
    Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8>
    
    In [3]: reload(sys)
    <module 'sys' (built-in)>
    
    In [4]: sys.stdout
    Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0>
    
    In [11]: import IPython.terminal
    
    In [14]: IPython.terminal.interactiveshell.sys.stdout
    Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
    
  • теперь sys.setdefaultencoding() правильный

    все, что это влияет на неявное преобразование str<->unicode. Теперь,utf-8 это самая здравая кодировка на планете (обратная совместимость с ASCII и все), преобразование теперь "просто работает",что может пойти не так?

    Ну, ничего. И в этом заключается опасность.

    • там может быть какой-то код, который полагается на UnicodeError выбрасывается для ввода, отличного от ASCII, или выполняет транскодирование с обработчиком ошибок, что теперь приводит к неожиданному результату. И так как весь код тестируется с настройкой по умолчанию, вы находитесь строго на" неподдерживаемой " территории здесь, и никто не дает вам гарантии о том, как их код будет вести себя.
    • транскодирование может привести к неожиданным или непригодным результатам, если не все в системе использует UTF-8 потому что Python 2 на самом деле имеет несколько независимых "кодировки строк по умолчанию". (Помните, что программа должна работать для клиента, на оборудовании клиента.)
      • опять же, самое страшное-это вы никогда этого не узнаете потому, что преобразование неявное -- вы действительно не знаете, когда и где это происходит. (Python Zen, koan 2 ahoy!) Вы никогда не узнаете, почему (и если) ваш код работает на одной системе и ломается на другой. (Или еще лучше, работает в IDE и ломается приставка.)

Comments

    Ничего не найдено.