我见过很少的py脚本在脚本的顶部使用它。在什么情况下应该使用它?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
答案 0 :(得分:132)
根据文档:这允许您从默认ASCII切换到其他编码,例如UTF-8,只要必须将字符串缓冲区解码为unicode,Python运行时就会使用这些编码。
此功能仅在Python启动时可用,当Python扫描环境时。必须在系统范围的模块sitecustomize.py
中调用它。在评估此模块后,setdefaultencoding()
函数将从sys
模块中删除。
实际使用它的唯一方法是使用重新加载hack来恢复属性。
此外,始终不鼓励使用sys.setdefaultencoding()
,并且它已成为py3k中的无操作。 py3k的编码硬连接到“utf-8”并且更改它会引发错误。
我建议阅读一些指示:
答案 1 :(得分:51)
答案是从不! (除非你真的知道你在做什么)
解决方案的9/10倍可以通过正确理解编码/解码来解决。
1/10人的语言环境或环境定义不正确,需要设置:
PYTHONIOENCODING="UTF-8"
在他们的环境中修复控制台打印问题。
(突破以避免重复使用)更改了Python 2.x需要将Unicode()转换为str()时使用的默认编码/解码(和反之亦然)并没有给出编码。即:sys.setdefaultencoding("utf-8")
str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC")
在Python 2.x中,默认编码设置为ASCII,上面的示例将失败:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
(我的控制台配置为UTF-8,因此"€" = '\xe2\x82\xac'
,因此\xe2
上的例外情况)
或
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
将允许这些适用于我,但不一定适用于不使用UTF-8的用户。 ASCII的默认值可确保编码假设未被编入代码 sys.setdefaultencoding("utf-8")
也会出现修复sys.setdefaultencoding("utf-8")
sys.stdout.encoding
的副作用,用于将字符打印到控制台时使用。 Python使用用户的语言环境(Linux / OS X / Un * x)或代码页(Windows)来设置它。有时,用户的区域设置已损坏,只需要PYTHONIOENCODING
来修复控制台编码。
示例:
$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()
$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€
由于默认编码为ASCII,因此人们已经开发了针对Python 2.x的16年。已编写UnicodeError
异常处理方法来处理发现包含非ASCII的字符串的字符串到Unicode转换。
来自https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/
def welcome_message(byte_string):
try:
return u"%s runs your business" % byte_string
except UnicodeError:
return u"%s runs your business" % unicode(byte_string,
encoding=detect_encoding(byte_string))
print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))
在设置defaultencoding之前,此代码将无法解码ascii编码中的“Å”,然后进入异常处理程序以猜测编码并将其正确地转换为unicode。印刷:Angstrom(Å®)经营您的业务。一旦你将defaultencoding设置为utf-8,代码就会发现byte_string可以解释为utf-8,因此它会破坏数据并返回它:Angstrom(Ů)运行你的业务。
更改应该是常量将对您依赖的模块产生巨大影响。最好只修复进出代码的数据。
虽然在下面的示例中将默认编码设置为UTF-8不是根本原因,但它显示了如何屏蔽问题以及当输入编码更改时,代码如何以非显而易见的方式中断: UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 3131: invalid start byte
答案 2 :(得分:18)
#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u
chmod +x test.py
./test.py
moçambique
moçambique
./test.py > output.txt
Traceback (most recent call last):
File "./test.py", line 5, in <module>
print u
UnicodeEncodeError: 'ascii' codec can't encode character
u'\xe7' in position 2: ordinal not in range(128)
shell上的工作,不发送到sdtout, 所以这是一个解决方法,写入stdout。
我做了其他方法,如果没有定义sys.stdout.encoding,则不运行,或者换句话说,首先需要导出PYTHONIOENCODING = UTF-8来写入stdout。
import sys
if (sys.stdout.encoding is None):
print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
exit(1)
所以,使用相同的例子:
export PYTHONIOENCODING=UTF-8
./test.py > output.txt
将起作用
答案 3 :(得分:3)
第一个危险在于reload(sys)
。
重新加载模块时,实际上在运行时中获得了两个模块的副本。旧模块就像其他所有的Python对象一样,只要有引用它就会保持活动状态。因此,一半的对象将指向旧模块,一半指向新模块。当您进行一些更改时,当一些随机对象看不到更改时,您将永远不会看到它:
(This is IPython shell)
In [1]: import sys
In [2]: sys.stdout
Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8>
In [3]: reload(sys)
<module 'sys' (built-in)>
In [4]: sys.stdout
Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0>
In [11]: import IPython.terminal
In [14]: IPython.terminal.interactiveshell.sys.stdout
Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
现在,sys.setdefaultencoding()
正确
All that it affects is implicit conversion str<->unicode
。现在,utf-8
是地球上最安全的编码(向后兼容ASCII和所有),转换现在“正常”,可能出错?
好吧,什么都好。这就是危险。
UnicodeError
,或者使用错误处理程序进行转码,现在会产生意外结果。并且由于所有代码都使用默认设置进行测试,因此您严格遵守“不受支持”的区域,并且没有人能够保证代码的行为方式。