这里涉及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,在{}的情况下,它将按上述方式打印其{},从而完全避免了编码问题