Когда я запускаю свои приложения с консоли, у меня возникает много проблем с "не могу кодировать" и "не могу декодировать" с Python . Но в Eclipse PyDev IDE кодировка символов по умолчанию установлена на UTF-8 , и я в порядке.
Я искал установку кодировки по умолчанию, и люди говорят, что Python удаляет sys.setdefaultencoding
функцию при запуске, и мы не можем ее использовать.
Итак, какое лучшее решение для этого?
The best solution is to learn to use encode and decode correctly instead of using hacks.
Это, безусловно, было возможно с python2 за счет того, что всегда нужно помнить об этом / последовательно использовать свой собственный интерфейс. Мой опыт показывает, что это становится очень проблематичным, когда вы пишете код, который хотите работать как с python2, так и с python3.Ответы:
Вот более простой метод (взлом), который возвращает вам
setdefaultencoding()
функцию, которая была удалена изsys
:import sys # sys.setdefaultencoding() does not exist, here! reload(sys) # Reload does the trick! sys.setdefaultencoding('UTF8')
(Примечание для Python 3.4+:
reload()
находится вimportlib
библиотеке.)Однако это небезопасно : очевидно, что это взлом, поскольку
sys.setdefaultencoding()
он намеренно удаляетсяsys
при запуске Python. Повторное включение и изменение кодировки по умолчанию может нарушить код, в котором используется ASCII по умолчанию (этот код может быть сторонним, что обычно делает его исправление невозможным или опасным).источник
LC_CTYPE
(или в приложении проверить, правильно ли он настроен, и прервать работу с появлением значимого сообщения об ошибке).LC_CTYPE=C python -c 'import locale; print( locale.getpreferredencoding())'
Если вы получаете эту ошибку при попытке передать / перенаправить вывод вашего скрипта
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
Просто экспортируйте PYTHONIOENCODING в консоль, а затем запустите свой код.
export PYTHONIOENCODING=utf8
источник
LC_CTYPE
на что - то разумное вместо. Это делает счастливыми и все остальные программы.PYTHONIOENCODING=utf8
это не по умолчанию. Это приводит к тому, что сценарии ломаются только потому, чтоLC_ALL=C
Set LC_CTYPE to something sensible instead
Это разумное предложение. Это не работает так хорошо, когда вы пытаетесь распространить код, который просто работает в системе другого человека.C.utf8
языковой стандарт для обеспечения более разумного C. glibc upstream работает над его добавлением, поэтому, возможно, нам не следует обвинять Python в соблюдении настроек языкового стандарта \…?A) Для управления
sys.getdefaultencoding()
выходом:python -c 'import sys; print(sys.getdefaultencoding())'
ascii
затем
echo "import sys; sys.setdefaultencoding('utf-16-be')" > sitecustomize.py
а также
PYTHONPATH=".:$PYTHONPATH" python -c 'import sys; print(sys.getdefaultencoding())'
utf-16-be
Вы можете разместить свой sitecustomize.py выше в своем
PYTHONPATH
.Также вы можете попробовать
reload(sys).setdefaultencoding
@EOLБ) Для управления
stdin.encoding
иstdout.encoding
вы хотите установитьPYTHONIOENCODING
:python -c 'import sys; print(sys.stdin.encoding, sys.stdout.encoding)'
ascii ascii
затем
PYTHONIOENCODING="utf-16-be" python -c 'import sys; print(sys.stdin.encoding, sys.stdout.encoding)'
utf-16-be utf-16-be
Наконец: вы можете использовать A) или B) или оба!
источник
from __future__ import unicode_literals
см. обсуждениеНачиная с PyDev 3.4.1, кодировка по умолчанию больше не изменяется. Подробности смотрите в этом билете .
Для более ранних версий решение состоит в том, чтобы убедиться, что PyDev не работает с UTF-8 в качестве кодировки по умолчанию. В Eclipse запустите настройки диалога («запустить конфигурации», если я правильно помню); Вы можете выбрать кодировку по умолчанию на общей вкладке. Измените его на US-ASCII, если вы хотите, чтобы эти ошибки возникали «раньше» (другими словами: в вашей среде PyDev). Также см. Исходное сообщение в блоге для этого обходного пути .
источник
Что касается python2 (и только python2), некоторые из предыдущих ответов полагаются на использование следующего взлома:
import sys reload(sys) # Reload is a hack sys.setdefaultencoding('UTF8')
Не рекомендуется использовать его (отметьте это или это )
В моем случае это имеет побочный эффект: я использую ноутбуки ipython, и как только я запускаю код, функция «print» больше не работает. Я думаю, что у этого есть решение, но все же я думаю, что использование хака не должно быть правильным вариантом.
После того, как я попробовал много вариантов, тот, который работал у меня, использовал тот же код в
sitecustomize.py
, где этот фрагмент кода должен быть . После оценки этого модуля функция setdefaultencoding удаляется из sys.Итак, решение - добавить в файл
/usr/lib/python2.7/sitecustomize.py
код:import sys sys.setdefaultencoding('UTF8')
Когда я использую virtualenvwrapper, я редактирую файл
~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py
.И когда я использую с ноутбуками на Python и conda, это
~/anaconda2/lib/python2.7/sitecustomize.py
источник
Об этом есть содержательный пост в блоге.
См. Https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/ .
Я перефразирую его содержание ниже.
В python 2, который не был так строго типизирован в отношении кодировки строк, вы могли выполнять операции со строками с различным кодированием и добиваться успеха. Например, вернется следующее
True
.u'Toshio' == 'Toshio'
Это будет справедливо для каждой (нормальной, без префикса) строки, которая была закодирована
sys.getdefaultencoding()
, по умолчаниюascii
, но не для других.Кодировка по умолчанию должна была быть изменена в масштабе всей системы
site.py
, но не где-то еще. Хаки (также представленные здесь) для установки его в пользовательских модулях были всего лишь хаками, а не решением.Python 3 действительно изменил системную кодировку по умолчанию на utf-8 (когда LC_CTYPE поддерживает Unicode), но фундаментальная проблема была решена с помощью требования явно кодировать «байтовые» строки всякий раз, когда они используются со строками Unicode.
источник
Во-первых:
reload(sys)
и установка некоторой случайной кодировки по умолчанию только с учетом потребности в потоке выходного терминала - плохая практика.reload
часто меняет вещи в sys, которые были введены в действие в зависимости от среды, например потоки sys.stdin / stdout, sys.excepthook и т. д.Решение проблемы с кодированием на stdout
Лучшее решение, которое я знаю для решения проблемы кодирования
print
строк unicode и за пределами asciistr
(например, из литералов) в sys.stdout, это: позаботиться о sys.stdout (файловом объекте), который способен и необязательно толерантный в отношении потребностей:Когда
sys.stdout.encoding
этоNone
по какой - то причине, или несуществующего, или ошибочно ложной или «меньше» , чем стандартный вывод терминала или поток действительно способен, а затем попытаться обеспечить правильный.encoding
атрибут. Наконец, путем заменыsys.stdout & sys.stderr
на переводящий файловый объект.Когда терминал / поток по-прежнему не может кодировать все встречающиеся символы Unicode, и когда вы не хотите прерывать
print
их только из-за этого, вы можете ввести поведение «кодирование с заменой» в переводящем файловом объекте.Вот пример:
#!/usr/bin/env python # encoding: utf-8 import sys class SmartStdout: def __init__(self, encoding=None, org_stdout=None): if org_stdout is None: org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout) self.org_stdout = org_stdout self.encoding = encoding or \ getattr(org_stdout, 'encoding', None) or 'utf-8' def write(self, s): self.org_stdout.write(s.encode(self.encoding, 'backslashreplace')) def __getattr__(self, name): return getattr(self.org_stdout, name) if __name__ == '__main__': if sys.stdout.isatty(): sys.stdout = sys.stderr = SmartStdout() us = u'aouäöüфżß²' print us sys.stdout.flush()
Использование простых строковых литералов за пределами ascii в коде Python 2/2 + 3
Единственная веская причина изменить глобальную кодировку по умолчанию (только на UTF-8), я думаю, касается решения исходного кода приложения - а не из-за проблем с кодировкой потока ввода-вывода: для записи строковых литералов за пределами ascii в код без принудительного всегда использовать
u'string'
экранирование в стиле Unicode. Это можно сделать довольно последовательно (несмотря на то, что говорится в статье anonbadger ), позаботившись об исходном коде Python 2 или Python 2 + 3, который последовательно использует простые строковые литералы ascii или UTF-8 - поскольку эти строки потенциально подвергаются молчанию. преобразование юникода и переход между модулями или, возможно, переход на стандартный вывод. Для этого предпочтите "# encoding: utf-8
"или ascii (без объявления). Измените или удалите библиотеки, которые по-прежнему очень глупо фатально полагаются на ошибки кодирования ascii по умолчанию за пределами chr # 127 (что сегодня редко).И сделайте так при запуске приложения (и / или через sitecustomize.py) в дополнение к
SmartStdout
схеме выше - без использованияreload(sys)
:... def set_defaultencoding_globally(encoding='utf-8'): assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding) import imp _sys_org = imp.load_dynamic('_sys_org', 'sys') _sys_org.setdefaultencoding(encoding) if __name__ == '__main__': sys.stdout = sys.stderr = SmartStdout() set_defaultencoding_globally('utf-8') s = 'aouäöüфżß²' print s
Таким образом, строковые литералы и большинство операций (кроме итерации символов) работают комфортно, не думая о преобразовании в Unicode, как если бы был только Python3. Файловый ввод-вывод, конечно, всегда требует особого внимания к кодировкам - как и в Python3.
Примечание: простые строки затем неявно преобразуются из utf-8 в unicode in
SmartStdout
перед преобразованием в кодирование выходного потока.источник
Вот подход, который я использовал для создания кода, который был совместим как с python2, так и с python3 и всегда давал вывод utf8 . Я нашел этот ответ в другом месте, но не могу вспомнить источник.
Этот подход работает путем замены
sys.stdout
чего-то, что не совсем похоже на файл (но по-прежнему использует только вещи из стандартной библиотеки). Это вполне может вызвать проблемы для ваших базовых библиотек, но в простом случае, когда у вас есть хороший контроль над тем, как sys.stdout используется в вашей структуре, это может быть разумным подходом.sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')
источник
Это быстрый способ взлома для всех, кто (1) на платформе Windows (2) работает с Python 2.7 и (3) раздражен тем, что это хорошее программное обеспечение (то есть написанное не вами, поэтому не сразу является кандидатом для кодирования / декодирования печати). maneuvers) не будут отображать «красивые символы Юникода» в среде IDLE (Pythonwin печатает в Юникоде нормально), например, аккуратные символы логики первого порядка, которые Стефан Бойер использует в выводе своего педагогического средства доказательства в программе проверки логики первого порядка .
Мне не понравилась идея принудительной перезагрузки sys, и я не мог заставить систему сотрудничать с настройкой переменных среды, таких как PYTHONIOENCODING (попробовал прямую переменную среды Windows, а также сбросил ее в sitecustomize.py в пакетах сайтов как один liner = 'utf-8').
Итак, если вы хотите взломать свой путь к успеху, перейдите в каталог IDLE, обычно: «C: \ Python27 \ Lib \ idlelib». Найдите файл IOBinding.py. Сделайте копию этого файла и сохраните ее в другом месте, чтобы вы могли вернуться к исходному поведению, когда захотите. Откройте файл в idlelib с помощью редактора (например, IDLE). Перейдите в эту область кода:
# Encoding for file names filesystemencoding = sys.getfilesystemencoding() encoding = "ascii" if sys.platform == 'win32': # On Windows, we could use "mbcs". However, to give the user # a portable encoding name, we need to find the code page try: # --> 6/5/17 hack to force IDLE to display utf-8 rather than cp1252 # --> encoding = locale.getdefaultlocale()[1] encoding = 'utf-8' codecs.lookup(encoding) except LookupError: pass
Другими словами, закомментируйте исходную строку кода, следующую за ' попыткой ', которая делала переменную кодирования равной locale.getdefaultlocale (потому что это даст вам cp1252, который вам не нужен), и вместо этого переберите его в 'utf-8 '(добавив строку' encoding = 'utf-8 ', как показано).
Я считаю, что это влияет только на отображение IDLE в stdout, а не на кодировку, используемую для имен файлов и т. Д. (Которая получена ранее в файловой системе). Если у вас возникнут проблемы с любым другим кодом, который вы запустите в IDLE позже, просто замените файл IOBinding.py исходным немодифицированным файлом.
источник
Это устранило проблему для меня.
import os os.environ["PYTHONIOENCODING"] = "utf-8"
источник
Вы можете изменить кодировку всей вашей операционной системы. В Ubuntu это можно сделать с помощью
sudo apt install locales sudo locale-gen en_US en_US.UTF-8 sudo dpkg-reconfigure locales
источник