Python在何时,何地以及如何将隐式编码应用于字符串,或者隐式转码(转换)?
那些“默认”(即隐含)编码是什么?
例如,编码是什么:
字符串文字?
s = "Byte string with national characters"
us = u"Unicode string with national characters"
类型转换为Unicode或从Unicode转换为字节字符串?
data = unicode(random_byte_string)
当从文件或终端写入字节和Unicode字符串时?
print(open("The full text of War and Peace.txt").read())
最佳答案
这里涉及Python功能的多个部分:读取源代码并解析字符串文字,转码和打印。每个都有自己的约定。
简短答案:
出于代码解析的目的:str
(Py2)-不适用,从文件中获取原始字节unicode
(Py2)/ str
(Py3)-“源编码”,默认值为ascii
(Py2)和utf-8
(Py3)bytes
(Py3)-无,文字中禁止使用非ASCII字符
为了进行转码:
both(Py2)-sys.getdefaultencoding()
(ascii
几乎总是)
有些隐式转换通常会导致UnicodeDecodeError
/ UnicodeEncodeError
both(Py3)-无,在转换时必须明确指定编码
出于I / O的目的:unicode
(Py2)-<file>.encoding
如果已设置,否则sys.getdefaultencoding()
str
(Py2)-不适用,写入原始字节str
(Py3)-<file>.encoding
,始终设置且默认为locale.getpreferredencoding()
bytes
(Py3)-无,print
ing生成其repr()
首先,对一些术语进行澄清,以便您正确理解其余内容。解码是从字节到字符(Unicode或其他)的转换,而编码(作为一个过程)则相反。请参见The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) – Joel on Software以获取区别。
现在...
读取源代码并解析字符串文字
At the start of a source file, you can specify the file's "source encoding"(稍后将描述其确切的效果)。如果未指定,则Python 2的默认值为ascii
,Python 3的默认值为utf-8
。UTF-8BOM的作用与utf-8
编码声明相同。
Python 2
Python 2将源作为原始字节读取。看到Unicode文字时,它仅使用“源编码”来解析Unicode文字。 (It's more complicated than that under the hood但这是实际效果。)
> type t.py
#encoding: cp1251
s = "абвгд"
us = u"абвгд"
print repr(s), repr(us)
> py -2 t.py
'\xe0\xe1\xe2\xe3\xe4' u'\u0430\u0431\u0432\u0433\u0434'
<change encoding declaration in the file to cp866, do not change the contents>
> py -2 t.py
'\xe0\xe1\xe2\xe3\xe4' u'\u0440\u0441\u0442\u0443\u0444'
<transcode the file to utf-8, update declaration or replace with BOM>
> py -2 t.py
'\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3\xd0\xb4' u'\u0430\u0431\u0432\u0433\u0434'
因此,常规字符串将包含文件中的确切字节。 Unicode字符串将包含使用“源编码”解码文件字节的结果。
如果解码失败,您将得到一个
SyntaxError
。如果在未指定编码的情况下文件中包含非ASCII字符,则相同。最后,如果使用unicode_literals
future,则在解析时将任何常规字符串文字(in that file only)视为Unicode文字,这意味着所有含义。Python 3
Python 3使用“源编码”将整个源文件解码为Unicode字符序列。此后将进行任何解析。 (特别是,这使得在标识符中包含Unicode成为可能。)由于所有字符串文字现在都是Unicode,因此不需要其他转码。在字节文字中,禁止使用非ASCII字符(此类字节必须使用转义序列指定),从而完全避免了该问题。
转码
根据开始时的说明:
str
-字节=>只能被decode
d(直接,即;详细信息如下)unicode
-字符=>只能是encode
dPython 2
在这两种情况下,如果未指定编码,则使用
sys.getdefaultencoding()
。它是ascii
(除非您取消注释site.py
,or do some other hacks中的are a recipe for disaster中的代码块)。因此,出于代码转换的目的,sys.getdefaultencoding()
是“字符串的默认编码”。现在,有一个警告:
在转换
decode()
时隐式完成了encode()
和str<->unicode
的默认编码:以字符串格式(关于SO的
UnicodeDecodeError
/ UnicodeEncodeError
问题的三分之一与此有关)尝试
encode()
一个str
或decode()
一个unicode
时(SO问题的第二三分之一)Python 3
根本没有“默认编码”:现在禁止在
str
和bytes
之间进行隐式转换。(随着来自困惑用户的大量SO问题的证明,事实证明,这带来的麻烦多于其价值。)
bytes
只能是decode
d和str
-encode
d,并且encoding
参数是必需的。转换
bytes->str
(隐式包含)会生成其repr()
(仅对打印有用),从而完全避免了编码问题禁止转换
str->bytes
列印
This matter与变量的值无关,但与变量
print
时在屏幕上看到的内容有关–以及UnicodeEncodeError
时是否会得到print
。Python 2
如果设置了
unicode
,则将encode
设置为<file>.encoding
。否则,将其隐式转换为str
。 (UnicodeEncodeError
SO问题的最后三分之一属于此处。)对于标准流,在启动时会从各种特定于环境的来源中猜测流的编码,并且可以使用
PYTHONIOENCODING
envvar覆盖流的编码。str
的字节按原样发送到OS流。您将在屏幕上看到哪些特定字符取决于终端的编码(如果它类似于UTF-8,则如果打印无效的UTF-8字节序列,您可能什么也看不到)。Python 3
更改为:
现在,使用文本与二进制
file
开头的mode
本身对应地接受str
或bytes
,并且完全拒绝处理错误的类型。文本模式文件始终设置为encoding
,即locale.getpreferredencoding(False)
being the default。文本流的
print
仍将所有内容隐式转换为str
,在bytes
的情况下,按照上述方法打印其repr()
,从而完全避免了编码问题
关于python - Python默认字符串编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49991870/