更改Python的默认编码?

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

我四处寻找设置默认编码,并且有人说Python在启动时删除了sys.setdefaultencoding函数,我们不能使用它。

那么最好的解决scheme是什么?

下面是一个简单的方法(黑客),可以让你回到从sys中删除的setdefaultencoding()函数:

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

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

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

你也可以尝试通过@EOL reload(sys).setdefaultencoding .setdefaultencoding

B)要控制stdin.encodingstdout.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)两者兼而有之!

如果在尝试pipe道/redirect脚本的输出时遇到此错误

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

只需在控制台中输出PYTHONIOENCODING,然后运行你的代码。

export PYTHONIOENCODING=utf8

从PyDev 3.4.1开始,默认编码不再被改变。 详情请看这张票 。

对于早期版本,解决scheme是确保PyDev不以UTF-8作为默认编码运行。 在Eclipse下,运行对话框设置(如果我没有记错,运行configuration); 您可以select公共选项卡上的默认编码。 如果你想在“早期”出现这些错误(换句话说就是在你的PyDev环境中),把它改为US-ASCII。 另请参阅此解决方法的原始博客文章 。

有一个有见地的博客文章。

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

我在下面解释它的内容。

在python 2中,对于string的编码没有强烈的types,你可以对不同编码的string执行操作,并成功。 例如以下将返回True

 u'Toshio' == 'Toshio' 

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

默认编码意味着在site.py系统范围内更改,而不是其他地方。 黑客(也在这里介绍)将其设置在用户模块只是:黑客,而不是解决scheme。

Python 3确实已经将系统编码更改为默认为utf-8(当LC_CTYPE是unicode-aware时),但是基本问题已经解决,只要使用unicodestring就要求显式编码“字节”string。

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

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

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

在我的情况下,它有一个副作用:我使用ipython笔记本,一旦我运行的代码“打印”function不再起作用。 我想这将有解决办法,但我仍然认为使用黑客应该不是正确的select。

尝试了很多select之后,为我工作的那个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

你想写西class牙语单词(para escribir lañen python)

 #!/usr/bin/env python # -*- coding: iso-8859-15 -*- print "Piña" 

首先: reload(sys)并设置一些随机的默认编码,只是针对输出terminalstream的需求是不好的做法。 reload经常会改变已经放置到位的sys依赖于环境的东西 – 例如sys.stdin / stdout streams,sys.excepthook等。

解决stdout上的编码问题

我知道解决在sys.stdout上print unicodestring和beyond-ascii str (例如从文本)的编码问题的最佳解决scheme是:处理sys.stdout(文件类对象),它是能力和任意容忍关于需要:

  • sys.stdout.encoding由于某种原因,或者不存在,或者错误的错误或者比标准输出terminal或者stream真正能够实现的更less的时候,则尝试提供一个正确的.encoding属性。 最后通过replacesys.stdout & sys.stderr一个翻译类似文件的对象。

  • 当terminal/stream仍然不能编码所有发生的Unicode字符,并且当你不想因此print ,可以在翻译的文件类对象中引入编码replace行为。

这里是一个例子:

 #!/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() 

在Python 2/2 + 3代码中使用beyond-ascii纯文本string

改变全局默认编码的唯一好理由(仅适用于UTF-8)我认为是关于应用程序源代码的决定 – 而不是因为I / Ostream编码问题:为了将不超过ascii的string文字写入代码而不被强制总是使用u'string'风格的unicode转义。 通过照顾一个使用ascii或UTF-8纯文本string的Python 2或Python 2 + 3源代码基础,可以一致地完成这项工作(尽pipeanonbadger的文章所述),只要这些string可能会进行沉默unicode转换和模块之间的移动或潜在的标准输出。 为此,更喜欢“ # encoding: utf-8 ”或ascii(没有声明)。 改变或丢弃仍然非常愚蠢地依赖于chr#127之外的ascii默认编码错误的库(这在今天很less见)。

除了上面的SmartStdoutscheme之外,还可以在应用程序启动(和/或通过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 

这种方式string文字和大多数操作(字符迭代除外)工作舒适,而不考虑unicode转换,就好像只有Python3。 文件I / O当然总是需要特别注意编码 – 就像在Python3中一样。

注意:在转换为输出streamSmartStdout之前, SmartStdoutstring会在SmartStdout从utf-8隐式转换为unicode。

这里是我用来生成与python2python3兼容的代码的方法,并且总是生成utf8输出。 我在其他地方find了这个答案,但我不记得来源。

这种方法通过将sys.stdoutreplace为sys.stdout 文件的东西 (但仍然只使用标准库中的东西)来工作。 这可能会导致您的底层库问题,但是在您可以很好地控制sys.stdout如何在您的框架中使用的情况下,这可能是一个合理的方法。

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

(1)在Windows平台(2)运行Python 2.7和(3)因为一个很好的软件(即不是你写的,所以不立即成为编码/解码打印的候选人)在IDLE环境中不会显示“漂亮的unicode字符”(Pythonwin打印unicode很好),例如,Stephan Boyer在First Order Logic Prover的教学certificate器的输出中使用的整齐的First Order Logic符号。

我不喜欢强制系统重新加载的想法,我不能让系统配合设置环境variables,如PYTHONIOENCODING(尝试直接的Windows环境variables,并将其放在站点包中的sitecustomize.py作为一个liner ='utf-8')。

所以,如果你愿意闯入成功的话,进入你的IDLE目录,通常是:“C:\ Python27 \ Lib \ idlelib”find文件IOBinding.py。 复制该文件并将其存储在其他位置,以便在您select时恢复到原始行为。 使用编辑器(例如,IDLE)在idlelib中打开文件。 转到此代码区:

 # 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 ”后的原始代码行,使得编码variables等于locale.getdefaultlocale (因为这会给你不需要的cp1252),而是强行将它强制为“utf-8 '(如图所示,通过添加' encoding ='utf-8 '行)。

我相信这只影响空闲显示标准输出,而不是用于文件名等编码(这是在文件系统编码之前获得)。 如果您以后在IDLE中运行的任何其他代码有问题,则只需将IOBinding.py文件replace为原始未修改的文件即可。