Python 默认字符串编码
Python default string encoding
Python 何时、何地以及如何对字符串隐式应用编码或隐式转码(转换)?
那些“默认”(即隐含的)编码是什么?
例如编码是什么:
个字符串文字?
s = "Byte string with national characters"
us = u"Unicode string with national characters"
与 Unicode 进行类型转换时的字节字符串?
data = unicode(random_byte_string)
当写入字节和 Unicode 字符串时to/from文件还是终端?
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) -- none, literal 中禁止非ASCII字符
- 为了转码:
- both (Py2) --
sys.getdefaultencoding()
(ascii
几乎总是)
- 存在隐式转换,通常会导致
UnicodeDecodeError
/UnicodeEncodeError
- both (Py3) -- none,转换时必须明确指定编码
- 为了 I/O 的目的:
unicode
(Py2) -- <file>.encoding
如果设置,否则 sys.getdefaultencoding()
str
(Py2) -- 不适用,写入原始字节
str
(Py3) -- <file>.encoding
,始终设置并默认为 locale.getpreferredencoding()
bytes
(Py3) -- none, 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"(具体作用后述)。如果未指定,则默认为 ascii
for Python 2 和 utf-8
for Python 3。UTF-8 BOM 与 utf-8
编码具有相同的效果宣言.
Python 2
Python 2 将源作为原始字节读取。当它看到一个 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 字符,则相同。最后,if unicode_literals
future is used, any regular string literals (in that file only) 在解析时被视为 Unicode 文字,这意味着什么。
Python 3
Python 3 用“源代码编码”将整个源文件解码成Unicode字符序列。之后进行任何解析。 (特别是,这使得在标识符中使用 Unicode 成为可能。)由于所有字符串文字现在都是 Unicode,因此不需要额外的转码。在字节字面量中,禁止使用非 ASCII 字符(此类字节必须使用转义序列指定),完全避免了这个问题。
转码
根据开头的说明:
str
(Py2)/bytes
(Py3) -- bytes => 只能是decode
d (直接,即;详情如下)
unicode
(Py2)/str
(Py3) -- 字符 => 只能是encode
d
Python 2
在这两种情况下,如果未指定编码,则使用 sys.getdefaultencoding()
。它是 ascii
(除非您取消注释 site.py
、or do some other hacks which are a recipe for disaster 中的代码块)。所以,为了转码,sys.getdefaultencoding()
是“字符串的默认编码”。
现在,请注意:
a decode()
和 encode()
-- 使用默认编码 -- 在转换 str<->unicode
:[=196= 时隐式完成]
- 字符串格式(Stack Overflow 上
UnicodeDecodeError
/UnicodeEncodeError
的三分之一问题与此有关)
- 当尝试
encode()
a str
或 decode()
a unicode
(Stack Overflow 问题的第二个三分之一)
Python 3
根本没有“默认编码”:现在禁止 str
和 bytes
之间的隐式转换。
bytes
只能是decode
d和str
--encode
d,encoding
参数是必须的。
- 转换
bytes->str
(包括隐式)生成其 repr()
(仅对调试打印有用),完全避免编码问题
- 禁止转换
str->bytes
正在打印
This matter 与变量的值无关,但与你在 print
ed 时在屏幕上看到的内容有关——以及当 [=] 时你是否会得到 UnicodeEncodeError
29=]ing.
Python 2
- A
unicode
是 encode
d,如果设置了 <file>.encoding
;否则,它会按照上述隐式转换为 str
。 (UnicodeEncodeError
SO 问题的最后三分之一落在这里。)
- 对于标准流,流的编码是在启动时从各种特定于环境的来源猜测的,并且可以用
PYTHONIOENCODING
环境变量覆盖。
str
的字节按原样发送到 OS 流。您将在屏幕上看到哪些具体字形取决于您终端的编码设置(如果它是类似 UTF-8 的东西,如果您打印一个无效的 UTF-8 字节序列,您可能什么也看不到)。
Python 3
变化是:
- 现在
file
s 打开文本与二进制 mode
本机接受 str
或 bytes
,相应地,完全拒绝处理错误的类型。文本模式文件总是有一个 encoding
集,locale.getpreferredencoding(False)
being the default.
文本流的 print
仍然隐式地将所有内容转换为 str
,在 bytes
的情况下,按照上述打印其 repr()
,从而避免了编码问题一共
隐式编码作为存储的内部格式strings/arrays:你不应该关心编码。事实上,Python 以 Python 内部方式解码 个字符。它大部分是透明的。只是想象它是一个 Unicode 文本,或者一个字节序列,以一种抽象的方式。
Python 3.x 中的内部编码因“较大”字符而异。可能是 UTF-8/ASCII (for ASCII strings), UTF-16 or UTF-32。当你使用字符串时,就像你有一个 Unicode 字符串(如此抽象,不是真正的编码)。如果你不会用C编程或者你使用了一些特殊的函数(内存视图),你将永远看不到内部编码。
字节只是实际内存的一个视图。 Python 解释为 unsigned char
。但是同样,通常你应该只考虑它是什么序列,而不是内部编码。
Python 2 的字节和字符串为无符号字符,Unicode 为 UCS-2(因此 65535 以上的代码点将用 Python 中的两个字符 (UCS-2) 编码2,Python3).
中只有一个字符 (UTF-32)
Python 何时、何地以及如何对字符串隐式应用编码或隐式转码(转换)?
那些“默认”(即隐含的)编码是什么?
例如编码是什么:
个字符串文字?
s = "Byte string with national characters" us = u"Unicode string with national characters"
与 Unicode 进行类型转换时的字节字符串?
data = unicode(random_byte_string)
当写入字节和 Unicode 字符串时to/from文件还是终端?
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) -- none, literal 中禁止非ASCII字符
- 为了转码:
- both (Py2) --
sys.getdefaultencoding()
(ascii
几乎总是)- 存在隐式转换,通常会导致
UnicodeDecodeError
/UnicodeEncodeError
- 存在隐式转换,通常会导致
- both (Py3) -- none,转换时必须明确指定编码
- both (Py2) --
- 为了 I/O 的目的:
unicode
(Py2) --<file>.encoding
如果设置,否则sys.getdefaultencoding()
str
(Py2) -- 不适用,写入原始字节str
(Py3) --<file>.encoding
,始终设置并默认为locale.getpreferredencoding()
bytes
(Py3) -- none,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"(具体作用后述)。如果未指定,则默认为 ascii
for Python 2 和 utf-8
for Python 3。UTF-8 BOM 与 utf-8
编码具有相同的效果宣言.
Python 2
Python 2 将源作为原始字节读取。当它看到一个 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 字符,则相同。最后,if unicode_literals
future is used, any regular string literals (in that file only) 在解析时被视为 Unicode 文字,这意味着什么。
Python 3
Python 3 用“源代码编码”将整个源文件解码成Unicode字符序列。之后进行任何解析。 (特别是,这使得在标识符中使用 Unicode 成为可能。)由于所有字符串文字现在都是 Unicode,因此不需要额外的转码。在字节字面量中,禁止使用非 ASCII 字符(此类字节必须使用转义序列指定),完全避免了这个问题。
转码
根据开头的说明:
str
(Py2)/bytes
(Py3) -- bytes => 只能是decode
d (直接,即;详情如下)unicode
(Py2)/str
(Py3) -- 字符 => 只能是encode
d
Python 2
在这两种情况下,如果未指定编码,则使用 sys.getdefaultencoding()
。它是 ascii
(除非您取消注释 site.py
、or do some other hacks which are a recipe for disaster 中的代码块)。所以,为了转码,sys.getdefaultencoding()
是“字符串的默认编码”。
现在,请注意:
a
decode()
和encode()
-- 使用默认编码 -- 在转换str<->unicode
:[=196= 时隐式完成]- 字符串格式(Stack Overflow 上
UnicodeDecodeError
/UnicodeEncodeError
的三分之一问题与此有关) - 当尝试
encode()
astr
或decode()
aunicode
(Stack Overflow 问题的第二个三分之一)
- 字符串格式(Stack Overflow 上
Python 3
根本没有“默认编码”:现在禁止 str
和 bytes
之间的隐式转换。
bytes
只能是decode
d和str
--encode
d,encoding
参数是必须的。- 转换
bytes->str
(包括隐式)生成其repr()
(仅对调试打印有用),完全避免编码问题 - 禁止转换
str->bytes
正在打印
This matter 与变量的值无关,但与你在 print
ed 时在屏幕上看到的内容有关——以及当 [=] 时你是否会得到 UnicodeEncodeError
29=]ing.
Python 2
- A
unicode
是encode
d,如果设置了<file>.encoding
;否则,它会按照上述隐式转换为str
。 (UnicodeEncodeError
SO 问题的最后三分之一落在这里。)- 对于标准流,流的编码是在启动时从各种特定于环境的来源猜测的,并且可以用
PYTHONIOENCODING
环境变量覆盖。
- 对于标准流,流的编码是在启动时从各种特定于环境的来源猜测的,并且可以用
str
的字节按原样发送到 OS 流。您将在屏幕上看到哪些具体字形取决于您终端的编码设置(如果它是类似 UTF-8 的东西,如果您打印一个无效的 UTF-8 字节序列,您可能什么也看不到)。
Python 3
变化是:
- 现在
file
s 打开文本与二进制mode
本机接受str
或bytes
,相应地,完全拒绝处理错误的类型。文本模式文件总是有一个encoding
集,locale.getpreferredencoding(False)
being the default.
文本流的 print
仍然隐式地将所有内容转换为str
,在bytes
的情况下,按照上述打印其repr()
,从而避免了编码问题一共
隐式编码作为存储的内部格式strings/arrays:你不应该关心编码。事实上,Python 以 Python 内部方式解码 个字符。它大部分是透明的。只是想象它是一个 Unicode 文本,或者一个字节序列,以一种抽象的方式。
Python 3.x 中的内部编码因“较大”字符而异。可能是 UTF-8/ASCII (for ASCII strings), UTF-16 or UTF-32。当你使用字符串时,就像你有一个 Unicode 字符串(如此抽象,不是真正的编码)。如果你不会用C编程或者你使用了一些特殊的函数(内存视图),你将永远看不到内部编码。
字节只是实际内存的一个视图。 Python 解释为 unsigned char
。但是同样,通常你应该只考虑它是什么序列,而不是内部编码。
Python 2 的字节和字符串为无符号字符,Unicode 为 UCS-2(因此 65535 以上的代码点将用 Python 中的两个字符 (UCS-2) 编码2,Python3).
中只有一个字符 (UTF-32)