Changing default encoding of Python?
当我从控制台运行应用程序时,我有许多关于Python的"无法编码"和"无法解码"问题。但是在EclipsePydev IDE中,默认的字符编码设置为utf-8,我很好。
我到处寻找设置默认编码的方法,人们说python在启动时会删除
那么,最好的解决方案是什么?
这里有一个简单的方法(hack),它返回从
1 2 3 4 | import sys # sys.setdefaultencoding() does not exist, here! reload(sys) # Reload does the trick! sys.setdefaultencoding('UTF8') |
不过,这样做并不安全:这显然是一次黑客攻击,因为当python启动时,
如果在尝试管道/重定向脚本输出时出现此错误
只需在控制台中导出pythonoencoding,然后运行代码。
a)控制
1 | python -c 'import sys; print(sys.getdefaultencoding())' |
然后
1 | echo"import sys; sys.setdefaultencoding('utf-16-be')"> sitecustomize.py |
和
1 | PYTHONPATH=".:$PYTHONPATH" python -c 'import sys; print(sys.getdefaultencoding())' |
你可以把你的sitecustomize.py放在你的
你也可以试试@eol的
b)为了控制
1 | python -c 'import sys; print(sys.stdin.encoding, sys.stdout.encoding)' |
然后
1 2 | PYTHONIOENCODING="utf-16-be" python -c 'import sys; print(sys.stdin.encoding, sys.stdout.encoding)' |
最后:您可以使用a)或b)或两者!
从pydev 3.4.1开始,默认编码不再被更改。详情请看这张票。
对于早期版本,解决方案是确保pydev不以utf-8作为默认编码运行。在Eclipse下,运行对话框设置("运行配置",如果我记得正确的话);您可以在公共选项卡上选择默认编码。如果您希望"早"出现这些错误(换句话说:在您的pydev环境中),请将其更改为us-ascii。还可以查看此解决方法的原始博客文章。
关于python2(仅限python2),以前的一些答案依赖于以下方法:
1 2 3 | import sys reload(sys) # Reload is a hack sys.setdefaultencoding('UTF8') |
不鼓励使用它(检查这个或这个)
在我的例子中,它有一个副作用:我正在使用ipython笔记本,一旦我运行代码,"print"功能就不再有效。我想会有解决办法的,但我仍然认为使用黑客不应该是正确的选择。
在尝试了许多选择之后,对我有用的一个选择是在
因此,解决方案是将代码附加到文件
1 2 | import sys sys.setdefaultencoding('UTF8') |
当我使用virtualenvwrapper时,我编辑的文件是
当我使用python笔记本和conda时,它是
关于它,有一篇有见地的博客文章。
请参阅https://anonbadger.wordpress.com/2015/06/16/why sys setdefaultencoding will break code/。
我将其内容解释如下。
在python 2中,对于字符串的编码没有强类型化,您可以对不同编码的字符串执行操作,然后成功。例如,以下内容将返回
1 | u'Toshio' == 'Toshio' |
对于在
在
python 3确实将系统编码改为默认的utf-8(当lc ctype支持Unicode时),但基本问题得到了解决,因为需要在与Unicode字符串一起使用时显式编码"byte"字符串。
这解决了我的问题。
1 2 | import os os.environ["PYTHONIOENCODING"] ="utf-8" |
型
首先:
解决stdout上的编码问题
我所知道的解决e sys.stdout上的
- 百万千克1
当
百万千克1百万千克1
当终端/流仍然无法对所有发生的unicode字符进行编码时,并且当您不想仅仅因为这一点而破坏
百万千克1
型
这里有一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/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??üф??2' print us sys.stdout.flush() |
在python 2/2+3代码中使用超越ASCII的纯字符串文本
我认为更改全局默认编码(仅适用于UTF-8)的唯一好理由是考虑应用程序源代码决策,而不是因为I/O流编码问题:将ASCII字符串以外的文字写入代码,而不必强制始终使用
并且在应用程序启动时(和/或通过sitecustomize.py)这样做,除了上面的
1 2 3 4 5 6 7 8 9 10 11 12 | ... 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??üф??2' print s |
号
这样,字符串文本和大多数操作(字符迭代除外)都可以在不考虑Unicode转换的情况下正常工作,就好像只有python3一样。文件I/O当然总是需要特别注意编码——就像python3一样。
注意:在转换为输出流编码之前,plains字符串在
对于那些(1)在运行python 2.7和(3)的Windows平台(2)上运行python的人来说,这是一个很快的黑客攻击,因为一个好的软件(即,不是由您编写的,所以不是立即进行编码/解码打印操作的候选软件)不会在空闲环境中显示"漂亮的unicode字符"(pythonwin打印unicode fine),例如,t他整洁的一阶逻辑符号,斯蒂芬博伊尔使用的输出从他的教学证明在一阶逻辑证明。
我不喜欢强制系统重新加载的想法,也无法让系统配合设置诸如pythonioencoding之类的环境变量(尝试了direct windows环境变量,并将其作为一个liner='utf-8')放到sitecustomize.py的站点包中。
因此,如果你愿意通过黑客手段获得成功,请转到空闲目录,通常是:"C:python27libidlelib"找到文件iobinding.py。制作该文件的副本并将其存储在其他地方,以便在选择时恢复到原始行为。用编辑器打开idlelib中的文件(例如idle)。转到此代码区域:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # 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的"try"后面注释原始代码行(因为这样会给您提供不需要的cp1252),而将其强制为"utf-8"(如图所示添加"encoding='utf-8")。
我相信这只会影响到stdout的空闲显示,而不会影响用于文件名等的编码(之前在filesystemcodeging中获得)。如果以后在空闲状态下运行的任何其他代码有问题,只需将iobinding.py文件替换为原始的未修改文件即可。
型
下面是我用来生成与python2和python3兼容并始终生成utf8输出的代码的方法。我在别处找到了这个答案,但我记不清来源。
这种方法的工作原理是将
1 | sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8') |
你想写西班牙语单词吗?恩蟒)
1 2 3 4 | #!/usr/bin/env python # -*- coding: iso-8859-15 -*- print"Pi?a" |