这里涉及Python的多个功能部分:读取源代码并解析字符串文本,转码,以及打印。每个人都有自己的习惯。在

简短回答:为了进行代码解析:

str(Py2)不适用,从文件中提取原始字节

unicode(Py2)/str(Py3)“源代码编码”,默认值为ascii(Py2)和{}(Py3)

bytes(Py3)无,文本中禁止使用非ascii字符

为了转码:

两者(Py2)sys.getdefaultencoding()(ascii几乎总是)

有一些隐式转换通常会导致UnicodeDecodeError/UnicodeEncodeError

转换时必须显式指定编码

对于I/O:

unicode(Py2).encoding如果设置,否则{}

^{py>(raw)字节不适用于str(Py3).encoding,始终设置并默认为locale.getpreferredencoding()

bytes(Py3)none,printing生成它的repr()

现在。。。在

读取源代码并解析字符串文本

At the start of a source file, you can specify the file's "source encoding"(其确切效果将在后面描述)。如果未指定,则Python2的默认值为ascii,Python3的默认值为utf-8。UTF-8bom与utf-8编码声明具有相同的效果。在

Python2

python2以原始字节的形式读取源代码。它只在看到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'
> py -2 t.py
'\xe0\xe1\xe2\xe3\xe4' u'\u0440\u0441\u0442\u0443\u0444'
> py -2 t.py
'\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3\xd0\xb4' u'\u0430\u0431\u0432\u0433\u0434'

因此,常规字符串将包含文件中的确切字节。和Unicode字符串将包含使用“源编码”解码文件字节的结果。

如果解码失败,您将得到一个SyntaxError。如果没有指定编码,文件中有非ascii字符,则相同。最后,如果使用^{} future,则在解析时,任何常规的字符串文本(in that file only)都被视为Unicode文本,这意味着什么。在

Python3

python3用“source encoding”将整个源文件解码为Unicode字符序列。任何解析都是在这之后完成的。(特别是,这使得在标识符中使用Unicode是可能的)由于所有字符串现在都是Unicode,所以不需要额外的代码转换。在字节文字中,禁止使用非ascii字符(这些字节必须用转义序列指定),从而完全避免了这个问题。在

转码

根据开始时的澄清:str字节=>只能是decoded(直接,即,详细信息如下)

unicode字符=>只能是encoded

Python2

在这两种情况下,如果未指定编码,则使用sys.getdefaultencoding()。它是ascii为了转码,sys.getdefaultencoding()是“字符串的默认编码”。

现在,有个警告:使用默认编码的decode()和{}在转换str<->unicode时隐式完成:在字符串格式中(SO上的UnicodeDecodeError/UnicodeEncodeError问题中有三分之一与此有关)

当尝试encode()astr或decode()aunicode(SO问题的第2/3)

Python3

根本没有“默认编码”:在str和bytesi之间的隐式转换现在禁止。

(困惑的用户提出的如此多的问题证明了这一点,事实证明这是一件麻烦事bytes只能是decoded和strencoded,并且encoding参数是必需的。在

转换bytes->str(包括隐式)将生成其repr()(这只对打印有用),完全避免了编码问题

禁止转换str->bytes

印刷

This matter与变量的值无关,但与您在print编辑时在屏幕上看到的内容以及在print时是否会得到UnicodeEncodeError。在

Python2如果设置了unicode,则unicode是encoded;否则,按照上面的方法隐式转换为str。(最后三分之一的问题属于这里。)

对于标准流,流的编码是在启动时从各种特定于环境的源猜测的,并且可以用PYTHONIOENCODINGenvvar重写。在

str的字节按原样发送到OS流。您将在屏幕上看到哪些特定字符取决于终端的编码(如果它类似于UTF-8,那么如果您打印的字节序列是无效的UTF-8,则可能看不到任何内容)。在

Python3

变化包括:现在,file以文本对二进制文件mode打开,相应地接受str或{},并直接拒绝处理错误的类型。文本模式文件总是有一个encoding集,^{} being the default。在

^对于文本流,{}仍然隐式地将所有内容转换为str,在{}的情况下,它将按上述方式打印其{},从而完全避免了编码问题