tl;博士
答案是从不! (除非你真的知道自己在做什么)
正确理解编码/解码可以解决9/10倍的解决方案。
1/10 人的语言环境或环境定义不正确,需要设置:
PYTHONIOENCODING="UTF-8"
在他们的环境中修复控制台打印问题。
它有什么作用?
sys.setdefaultencoding("utf-8")(为了避免重复使用而删除)更改了 Python 2.x 需要将 Unicode() 转换为 str() 时使用的默认编码/解码(反之亦然)反之亦然)并且没有给出编码。即:
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)
sys.setdefaultencoding("utf-8") 将允许这些为 me 工作,但不一定适用于不使用 UTF-8 的人。 ASCII 的默认设置确保不会将编码假设融入代码
控制台
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"
€
sys.setdefaultencoding("utf-8")有什么不好?
人们已经针对 Python 2.x 进行了 16 年的开发,因为他们理解默认编码是 ASCII。 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 (Å®) 经营您的业务。将默认编码设置为 utf-8 后,代码会发现 byte_string 可以解释为 utf-8,因此它将破坏数据并返回:Angstrom (Ů) 运行您的业务。
更改应该是常量的值将对您所依赖的模块产生巨大影响。最好只修复进出代码的数据。
示例问题
虽然将 defaultencoding 设置为 UTF-8 不是以下示例中的根本原因,但它显示了问题是如何被掩盖的,以及当输入编码发生变化时,代码如何以一种不明显的方式中断:
UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 3131: invalid start byte