更改Python的默认编码?

Ali*_*deh 127 python console encoding utf-8

当我从控制台运行我的应用程序时,我有很多"无法编码"和"无法解码"的Python问题.但是在Eclipse PyDev IDE中,默认字符编码设置为UTF-8,我很好.

我四处搜索设置默认编码,人们说Python sys.setdefaultencoding在启动时删除了该功能,我们无法使用它.

那么什么是最好的解决方案呢?

Eri*_*got 146

这是一个更简单的方法(hack),它返回setdefaultencoding()sys以下位置删除的函数:

import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys)  # Reload does the trick!
sys.setdefaultencoding('UTF8')
Run Code Online (Sandbox Code Playgroud)

但这不是一件安全的事情:这显然是一个黑客,因为在Python启动时sys.setdefaultencoding()故意将其删除sys.重新启用它并更改默认编码可能会破坏依赖于ASCII的默认代码(此代码可以是第三方,这通常会使修复它变得不可能或危险).

  • 你能否谈谈https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/?中提出的问题?(@ ibotty将它们提到上面) (4认同)
  • 我贬低了,因为这个答案没有帮助运行现有的应用程序(这是解释问题的一种方式),在编写/维护应用程序时是错误的,在编写库时是危险的.正确的方法是设置`LC_CTYPE`(或在应用程序中,检查它是否设置正确并使用有意义的错误消息中止). (4认同)

ima*_*man 63

如果在尝试管道/重定向脚本输出时出现此错误

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

只需在控制台中导出PYTHONIOENCODING,然后运行您的代码.

export PYTHONIOENCODING=utf8

  • Python3中的一个更大的错误是,'PYTHONIOENCODING = utf8`不是默认值.这使得脚本因为`LC_ALL = C`而中断 (5认同)
  • 将`LC_CTYPE`设置为合理的东西.它使所有其他节目也开心. (4认同)
  • 这是唯一对我有所帮助的解决方案. - 我在Debian 7上,语言环境设置有问题.谢谢. (2认同)

luk*_*mdo 51

A)控制sys.getdefaultencoding()输出:

python -c 'import sys; print(sys.getdefaultencoding())'
Run Code Online (Sandbox Code Playgroud)

ascii

然后

echo "import sys; sys.setdefaultencoding('utf-16-be')" > sitecustomize.py
Run Code Online (Sandbox Code Playgroud)

PYTHONPATH=".:$PYTHONPATH" python -c 'import sys; print(sys.getdefaultencoding())'
Run Code Online (Sandbox Code Playgroud)

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)'
Run Code Online (Sandbox Code Playgroud)

ascii ascii

然后

PYTHONIOENCODING="utf-16-be" python -c 'import sys; 
print(sys.stdin.encoding, sys.stdout.encoding)'
Run Code Online (Sandbox Code Playgroud)

utf-16-be utf-16-be

最后:您可以使用A)B)两者兼而有之!


Chr*_*heD 17

PyDev 3.4.1 开始,默认编码不再被更改.有关详细信息,请参阅此票

对于早期版本,解决方案是确保PyDev不以UTF-8作为默认编码运行.在Eclipse下,运行对话框设置("运行配置",如果我没记错的话); 您可以在常用选项卡上选择默认编码.如果您希望"早期"(换句话说:在PyDev环境中)出现这些错误,请将其更改为US-ASCII.另请参阅此解决方法的原始博客文章.


kir*_*ril 13

关于python2(仅限python2),前一些答案依赖于使用以下hack:

import sys
reload(sys)  # Reload is a hack
sys.setdefaultencoding('UTF8')
Run Code Online (Sandbox Code Playgroud)

不鼓励使用它(检查这个这个)

在我的情况下,它带来了副作用:我正在使用ipython笔记本,一旦我运行代码,'print'功能就不再起作用了.我想它会有解决方案,但我认为使用黑客攻击不应该是正确的选择.

在尝试了很多选项之后,那个适合我的选项就是使用相同的代码sitecustomize.py,而那段代码就是这样的.在评估该模块后,将从sys中删除setdefaultencoding函数.

所以解决方案是附加文件/usr/lib/python2.7/sitecustomize.py代码:

import sys
sys.setdefaultencoding('UTF8')
Run Code Online (Sandbox Code Playgroud)

当我使用virtualenvwrapper时,我编辑的文件是~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py.

当我使用python notebooks和conda时,它就是 ~/anaconda2/lib/python2.7/sitecustomize.py


ibo*_*tty 8

关于它的博客文章很有见地.

请参阅https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/.

我在下面解释它的内容.

在python 2中,对于字符串的编码没有强类型,你可以对不同编码的字符串执行操作,并且成功.例如,以下将返回True.

u'Toshio' == 'Toshio'
Run Code Online (Sandbox Code Playgroud)

这将适用于编码的每个(正常的,无前缀的)字符串,sys.getdefaultencoding()默认为ascii但不是其他字符串.

默认编码意味着在系统范围内更改site.py,但不在其他地方更改.在用户模块中设置它的hacks(也在这里展示)只是:hacks,而不是解决方案.

Python 3确实将系统编码更改为默认为utf-8(当LC_CTYPE具有unicode感知时),但是基本问题是通过在与unicode字符串一起使用时显式编码"字节"字符串的要求来解决的.


kxr*_*kxr 5

第一:reload(sys)仅根据输出终端流的需要设置一些随机默认编码是不好的做法。reload经常根据环境更改 sys 中已到位的内容 - 例如 sys.stdin/stdout 流、sys.excepthook 等。

\n\n

解决标准输出上的编码问题

\n\n

print我所知道的解决unicode 字符串和超越 ascii编码问题的最佳解决方案str是:处理 sys.stdout (类似文件的对象),它是有能力并且可以选择性地容忍以下需求:

\n\n
    \n
  • sys.stdout.encoding出于None某种原因,或不存在,或错误地为假或“小于”标准输出终端或流的实际能力时,则尝试提供正确的.encoding属性。最后通过替换sys.stdout & sys.stderr为类似文件的翻译对象。

  • \n
  • 当终端/流仍然无法对所有出现的 unicode 字符进行编码时,并且当您不想中断时print因此而破坏 \ 时,您可以在翻译类文件对象中引入编码与替换行为。

  • \n
\n\n

这里有一个例子:

\n\n
#!/usr/bin/env python\n# encoding: utf-8\nimport sys\n\nclass SmartStdout:\n    def __init__(self, encoding=None, org_stdout=None):\n        if org_stdout is None:\n            org_stdout = getattr(sys.stdout, \'org_stdout\', sys.stdout)\n        self.org_stdout = org_stdout\n        self.encoding = encoding or \\\n                        getattr(org_stdout, \'encoding\', None) or \'utf-8\'\n    def write(self, s):\n        self.org_stdout.write(s.encode(self.encoding, \'backslashreplace\'))\n    def __getattr__(self, name):\n        return getattr(self.org_stdout, name)\n\nif __name__ == \'__main__\':\n    if sys.stdout.isatty():\n        sys.stdout = sys.stderr = SmartStdout()\n\n    us = u\'aou\xc3\xa4\xc3\xb6\xc3\xbc\xd1\x84\xc5\xbc\xc3\x9f\xc2\xb2\'\n    print us\n    sys.stdout.flush()\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 Python 2 / 2 + 3 代码中使用 Beyond-ascii 纯字符串文字

\n\n

我认为更改全局默认编码(仅更改为 UTF-8)的唯一充分理由是考虑到应用程序源代码决策 - 而不是因为 I/O 流编码问题:为了在不强制的情况下将超出 ascii 的字符串文字写入代码始终使用u\'string\'unicode 转义样式。通过处理始终使用 ascii 或 UTF-8 纯字符串文字的 Python 2 或 Python 2 + 3 源代码基础,可以相当一致地完成此操作(尽管anonbadger的文章是这么说的) - 只要这些字符串可能会经历静默 unicode 转换并在模块之间移动或可能转到标准输出。为此,更喜欢“# encoding: utf-8 ”或 ascii(无声明)。更改或删除仍然以非常愚蠢的方式致命地依赖于 chr #127 之外的 ascii 默认编码错误的库(这在今天很少见)。

\n\n

除了SmartStdout上述方案之外,还可以在应用程序启动时(和/或通过 sitecustomize.py)执行此操作 - 不使用reload(sys)

\n\n
...\ndef set_defaultencoding_globally(encoding=\'utf-8\'):\n    assert sys.getdefaultencoding() in (\'ascii\', \'mbcs\', encoding)\n    import imp\n    _sys_org = imp.load_dynamic(\'_sys_org\', \'sys\')\n    _sys_org.setdefaultencoding(encoding)\n\nif __name__ == \'__main__\':\n    sys.stdout = sys.stderr = SmartStdout()\n    set_defaultencoding_globally(\'utf-8\') \n    s = \'aou\xc3\xa4\xc3\xb6\xc3\xbc\xd1\x84\xc5\xbc\xc3\x9f\xc2\xb2\'\n    print s\n
Run Code Online (Sandbox Code Playgroud)\n\n

这样,字符串文字和大多数操作(字符迭代除外)就可以舒适地工作,而无需考虑 unicode 转换,就好像只有 Python3 一样。\n文件 I/O 当然总是需要特别注意编码 - 就像 Python3 中一样。

\n\n

注意:普通字符串会从 utf-8 隐式转换为 unicodeSmartStdout注意:在转换为输出流编码之前,

\n


Att*_*igh 5

这是我用来生成与python2python3兼容并始终生成utf8输出的代码的方法。我在别处找到了这个答案,但我不记得出处了。

这种方法的工作原理是替换sys.stdout一些不太像文件的东西(但仍然只使用标准库中的东西)。这很可能会导致您的底层库出现问题,但在您可以很好地控制如何通过框架使用 sys.stdout 的简单情况下,这可能是一种合理的方法。

sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')
Run Code Online (Sandbox Code Playgroud)