Изменение кодировки по умолчанию для Python?

У меня есть много проблем "не могу кодировать" и "не могу декодировать" с Python, когда я запускаю свои приложения из консоль. Но в Eclipse PyDev IDE, по умолчанию кодировка символов установлена ​​на UTF-8, и я в порядке.

Я искал для настройки кодировки по умолчанию, и люди говорят, что Python удаляет функцию sys.setdefaultencoding при запуске, и мы не можем ее использовать.

Так какое лучшее решение для этого?

Ответ 1

Вот более простой метод (hack), который возвращает функцию setdefaultencoding(), которая была удалена из sys:

import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys)  # Reload does the trick!
sys.setdefaultencoding('UTF8')

Это не безопасно делать: это, очевидно, взлом, поскольку sys.setdefaultencoding() намеренно удаляется из sys при запуске Python. Повторное включение и изменение кодировки по умолчанию может привести к поломке кода, который полагается на ASCII по умолчанию (этот код может быть сторонним, что обычно фиксирует это невозможно или опасно).

Ответ 2

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

B) Для управления 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) или оба!

Ответ 3

Если вы получаете эту ошибку, когда пытаетесь передать/перенаправить вывод своего script

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

Просто экспортируйте PYTHONIOENCODING в консоли, а затем запустите свой код.

export PYTHONIOENCODING=utf8

Ответ 4

Начиная с PyDev 3.4.1, кодировка по умолчанию больше не изменяется. Подробнее см. этот билет.

Для более ранних версий решение состоит в том, чтобы убедиться, что PyDev не работает с UTF-8 в качестве кодировки по умолчанию. В Eclipse запустите диалоговые настройки ( "запустите конфигурацию", если я правильно помню); вы можете выбрать кодировку по умолчанию на общей вкладке. Измените его на US-ASCII, если вы хотите, чтобы эти ошибки были ранними (другими словами: в среде PyDev). Также см. оригинальное сообщение в блоге для этого обходного пути.

Ответ 5

Есть проницательное сообщение в блоге об этом.

См. 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-aware), но основная проблема была решена с требованием явно кодировать строки "байтов" всякий раз, когда они используются с строками unicode.

Ответ 6

Что касается python2 (и только python2), некоторые из предыдущих ответов полагаются на использование следующего взлома:

import sys
reload(sys)  # Reload is a hack
sys.setdefaultencoding('UTF8')

Не рекомендуется использовать его (отметьте this или this)

В моем случае он имеет побочный эффект: я использую 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 notebooks и conda, это ~/anaconda2/lib/python2.7/sitecustomize.py

Ответ 7

Вы хотите написать испанские слова (para escribir la ñ en python)

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

print "Piña"

Ответ 8

Во-первых: reload(sys) и установка какой-либо случайной кодировки по умолчанию только в отношении потребности в выходном терминальном потоке - это плохая практика. reload часто меняет объекты в sys, которые были установлены в зависимости от среды - например, sys.stdin/stdout, sys.excepthook и т.д.

Решение проблемы с кодировкой на stdout

Лучшее решение, которое я знаю для решения проблемы с кодировкой print 'строк unicode и за пределами ascii str (например, из литералов) на sys.stdout, - это: позаботиться о sys.stdout(file- подобный объект), который способен и, возможно, терпимо относиться к потребностям:

  • Когда sys.stdout.encoding по какой-то причине None или несуществующий, или ошибочно ложный или "меньше", чем то, на что способен терминал или поток stdout, затем попробуйте указать правильный .encoding. Наконец, заменив sys.stdout & sys.stderr на переводный файл-подобный объект.

  • Когда терминал/поток все еще не могут кодировать все возникающие символы юникода, и когда вы не хотите разорвать 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), я думаю, это решение приложения исходный код - и не из-за проблем с кодированием потока ввода-вывода: для записи string-ascii-string литералы в код, не будучи вынужденным всегда использовать 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

Таким образом, строковые литералы и большинство операций (кроме итерации символов) работают комфортно, не думая о преобразовании в Юникоде, как будто бы только Python3. Файловый ввод/вывод, конечно, всегда требует особой осторожности в отношении кодировок - как и в Python3.

Примечание. Строки равнины затем неявно преобразуются из utf-8 в unicode в SmartStdout перед преобразованием в обратный поток.

Ответ 9

Вот такой подход, который я использовал для создания кода, который был совместим как с python2, так и с python3 и всегда производил вывод utf8. Я нашел этот ответ в другом месте, но я не могу вспомнить источник.

Этот подход работает, заменив sys.stdout тем, что не является файловым (но все еще используется только в стандартной библиотеке). Это может вызвать проблемы для ваших базовых библиотек, но в простом случае, когда у вас есть хороший контроль над тем, как sys.stdout используется через ваши рамки, это может быть разумным подходом.

sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')

Ответ 10

Это быстрый взлом для всех, кто (1) на платформе Windows (2) работает Python 2.7 и (3) раздражен, потому что хороший кусок программного обеспечения (т.е. не написанный вами так не сразу кандидат для кодирования/декодирование печати) не будет отображать "симпатичные символы Юникода" в среде IDLE (Pythonwin печатает юникод в порядке), например, аккуратные символы логики первого порядка, которые использует Стефан Бойер на выходе из своей педагогической программы на Логический прогон первого порядка.

Мне не нравилась идея принудительного перезагрузки sys, и я не мог заставить систему сотрудничать с настройкой переменных окружения, таких как PYTHONIOENCODING (попробовал прямую переменную среды Windows, а также сбросил ее в файле sitecustomize.py в пакетах сайта как один вкладыш = '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
Другими словами, закомментируйте исходную строку кода после "try", которая делала переменную кодировки равной locale.getdefaultlocale(потому что это даст вам cp1252, который вам не нужен), а вместо этого перетащите ее в ' utf-8 '(добавив строку' encoding = 'utf-8', как показано).

Я считаю, что это влияет только на отображение IDLE на stdout, а не на кодировку, используемую для имен файлов и т.д. (что получено ранее в файловой системе). Если у вас возникла проблема с любым другим кодом, который вы запускаете в IDLE позже, просто замените файл IOBinding.py исходным немодифицированным файлом.