我花了几个小时来寻找Unicode字符串的问题,该问题被分解为Python(2.7)对我隐藏的东西,但我仍然不明白。首先,我尝试u".."在代码中一致地使用字符串,但这导致了声名狼藉UnicodeEncodeError。我尝试使用.encode('utf8'),但这也无济于事。最终,事实证明我不应该使用任何一种,它们都能自动完成。但是,我(在这里我要感谢一位帮助过我的朋友)在将我的头撞到墙上时确实发现了一些奇怪的东西。sys.getdefaultencoding()返回 ascii ,而sys.stdout.encoding返回 UTF-8 。1.在下面的代码中可以正常工作,而无需对sys和进行任何修改。2.引发UnicodeEncodeError。如果我使用更改默认系统编码 reload(sys).setdefaultencoding("utf8"),然后2.正常运行。我的问题是,为什么两个编码变量首先不同,如何在这段简单的代码中使用错误的编码?请不要发送给我Unicode HOWTO,在有关的数十个问题中,我显然已经读过它UnicodeEncodeError。
u".."
UnicodeEncodeError
.encode('utf8')
sys.getdefaultencoding()
sys.stdout.encoding
sys
reload(sys).setdefaultencoding("utf8")
# -*- coding: utf-8 -*- import sys class Token: def __init__(self, string, final=False): self.value = string self.final = final def __str__(self): return self.value def __repr__(self): return self.value print(sys.getdefaultencoding()) print(sys.stdout.encoding) # 1. myString = "I need 20 000€." tok = Token(myString) print(tok) reload(sys).setdefaultencoding("utf8") # 2. myString = u"I need 20 000€." tok = Token(myString) print(tok)
我的问题是为什么两个编码变量首先不同
它们有不同的用途。
sys.stdout.encoding应该是终端用来解释文本的编码,否则您可能会在输出中得到mojibake。在一个环境中可能是utf-8,在另一个环境中可能是cp437,等等。
sys.getdefaultencoding()在Python 2上用于隐式转换(未明确设置编码时),即Python 2可以将仅ascii的字节字符串和Unicode字符串混合在一起,例如,xml.etree.ElementTree将ascii范围内的文本存储为字节字符串,或者json.dumps()返回仅ascii的字节字符串而不是Unicode在Python 2中-可能是由于性能- 字节代表ASCII字符比Unicode便宜。Python 3禁止隐式转换。
xml.etree.ElementTree
json.dumps()
sys.getdefaultencoding()总是'ascii'在Python 2的所有系统上运行,除非您重写它,否则不要这样做,否则它可能会隐藏错误,并且由于隐式转换(使用可能错误的数据编码)而导致数据容易损坏。
'ascii'
顺便说一句,还有另一种sys.getfilesystemencoding()可能与两者不同的通用编码。sys.getfilesystemencoding()应该是用于编码OS数据(文件名,命令行参数,环境变量)的编码。
sys.getfilesystemencoding()
使用声明的源代码编码# -*- coding: utf-8 -*-可能与所有上述编码不同。
# -*- coding: utf-8 -*-
自然地,如果您从文件,网络中读取数据;它可能使用与上述字符不同的字符编码,例如,如果使用Windows ANSI编码保存在记事本中创建的文件,例如cp1252在另一个系统上,则所有标准编码都可能与此不同。
cp1252
重点是:出于与Python无关的原因,可能会有 多种 编码,为避免麻烦,请使用Unicode表示文本:在输入时尽快将编码后的文本转换为Unicode,然后将其编码为字节(可能使用其他编码)在输出时尽可能晚- 这就是所谓的Unicode三明治的概念。
如何在这段简单的代码中使用错误的编码?
您的第一个代码示例不正确。您在Python 2的字节字符串中使用了不应该使用的非ASCII文字字符。仅将字节字符串的文字用于二进制数据(或在必要时使用本机字符串)。I need 20 000Γé¼.如果您在任何不使用utf-8兼容编码的环境(例如Windows控制台)中使用Python 2运行该代码,则该代码可能会产生mojibake,例如(注意字符噪声)
I need 20 000Γé¼.
假设第二个代码示例reload(sys)不包含在其中,则可以。如果您不想在所有字符串文字前添加u''; 你可以用from __future__ import unicode_literals
reload(sys)
u''
from __future__ import unicode_literals
您的实际问题是UnicodeEncodeError错误,reload(sys)而不是正确的解决方案! 正确的解决方案是在POSIX()上LANG``LC_CTYPE正确配置语言环境,或者在输出重定向到管道/文件或安装以将Unicode打印到Windows控制台时设置PYTHONIOENCODINGenvvarwin-unicode-console。
LANG``LC_CTYPE
PYTHONIOENCODING
win-unicode-console