我在脚本顶部看到了几个使用此脚本的py脚本。在什么情况下应该使用它?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
我在脚本顶部看到了几个使用此脚本的py脚本。在什么情况下应该使用它?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Answers:
根据文档:这允许您从默认的ASCII切换到其他编码,例如UTF-8,Python运行时在必须将字符串缓冲区解码为unicode时将使用该编码。
此功能仅在Python扫描环境时在Python启动时可用。必须在系统范围的模块中调用,sitecustomize.py
评估完setdefaultencoding()
该sys
模块后,将从该模块中删除该功能。
实际使用它的唯一方法是通过将属性重新带回的重载hack。
此外,使用sys.setdefaultencoding()
一直气馁,它已成为一个无操作的py3k。py3k的编码硬连线到“ utf-8”,更改它会引发错误。
我建议您阅读一些指针:
sys.stdout
具有None
编码时,例如重定向Python程序的输出时)。
sys.setdefaultencoding()
始终不鼓励使用”
UTF-8
。 LC_ALL=en_US.UTF-8 python3 -c 'import sys; print(sys.stdout.encoding)'
给予UTF-8
但LC_ALL=C python3 -c 'import sys; print(sys.stdout.encoding)'
给予ANSI_X3.4-1968
(或其他)
答案是永不!(除非您真的知道自己在做什么)
在正确理解编码/解码的情况下,可以解决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
在将字符打印到控制台时,也具有出现fix的副作用。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。打印:埃斯特朗(Å®)经营您的业务。将defaultencoding设置为utf-8后,代码将发现byte_string可以解释为utf-8,因此它将处理数据并返回该值:Angstrom(Ů)经营您的业务。
更改应为常数的值将对您依赖的模块产生巨大影响。最好只修复代码中传入和传出的数据。
虽然在以下示例中将defaultencoding设置为UTF-8并不是根本原因,但它显示了如何掩盖问题以及如何在输入编码更改时以不明显的方式中断代码: UnicodeDecodeError:'utf8'编解码器可以在位置3131中解码字节0x80:无效的起始字节
sys.setdefaultencoding("utf-8")
,但最好使代码的行为更像Python3。现在是2017年。即使您在2015年写下答案时,我认为前瞻而不是后退已经更好。当我发现我的代码在Python 2中的行为取决于是否重定向输出时,这实际上是对我来说最简单的解决方案(Python 2的问题非常棘手)。不用说,我已经有了# coding: utf-8
,并且我不需要Python 3的任何解决方法(实际上我必须掩盖setdefaultencoding
使用版本检查)。
sys.setdefaultencoding("utf-8")
您有用,但不能使您的Py 2.x代码与Python 3兼容。它也不能修复假定默认编码为ASCII的外部模块。使您的代码与Python 3兼容非常简单,不需要这种讨厌的技巧。例如,为什么这会导致非常现实的问题,看到我与亚马逊的经验与这一假设搞乱:stackoverflow.com/questions/39465220/...
PYTHONIOENCODING="UTF-8"
帮助了我的Python2.7 Django-1.11环境。谢谢。
detect_encoding
。
detect_encoding
是一种可以根据语言线索检测字符串编码的方法。
#!/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
将工作
第一个危险在于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()
适当的
它所影响的只是隐式转换str<->unicode
。现在,这utf-8
是地球上最聪明的编码(向后兼容ASCII和所有语言),现在转换“正常”了,可能出什么问题了吗?
好吧,什么都可以。那就是危险。
UnicodeError
为非ASCII输入抛出的代码,或者使用错误处理程序进行代码转换,这现在会产生意外结果。而且,由于所有代码都是使用默认设置进行测试的,因此您在此处严格处于“不受支持”的范围,并且没人能保证它们的代码将如何运行。