当我们声明 # -*- coding: ... -*-(或只是 # coding: ...)时,我们是在告诉 Python 源文件保存在声明的编码中。
因此,编码声明很重要,但是在源文件在声明的编码中有效并且我们不使用u-literals 之前,更改声明的编码不会影响打印输出。
要检查最后一条语句,让我们看一下:
编码声明的效果。
1.语法错误测试。
首先,Python 使用 SyntaxError 测试的声明编码。
例如,让我们运行以下保存在utf-8中的源文件:
# -*- coding: utf-8 -*-
print repr('Á') # '\xc3\x81'
从打印输出中可以看出:Á 字符的 utf-8 字节为:\xc3\x81。
让我们更改声明的编码并再次运行文件:
# -*- coding: cp1252 -*-
print repr('Á')
现在它失败并出现错误:
SyntaxError: 'charmap' codec can't decode byte 0x81 in position 13: character maps to <undefined>
源仍在utf-8 中,但现在\xc3\x81 字节序列在声明的编码(cp1252)中无效,因为在此编码中\x81 字节映射到UNDEFINED。
同时é 字符的utf-8 字节为:\xc3\xa9,此字节序列在cp1252 中有效。因此,在这种情况下,声明哪种编码并不重要——utf-8 或cp1252——上面提到的字节将通过SyntaxError 测试:
# -*- coding: utf-8 -*-
print repr('é') # '\xc3\xa9'
# -*- coding: cp1252 -*-
print repr('é') # '\xc3\xa9'
然后它们将通过sys.stdout.encoding:
打印/解码
(大约如下例所示)
import sys
bytes_in = '\xc3\xa9'
enc_out = sys.stdout.encoding
chars_out = '\xc3\xa9'.decode(enc_out)
print chars_out # 'é' if enc_out == 'utf-8'
sys.stdout.encoding 取决于环境,不取决于声明的编码。
这就是为什么当源文件采用相同编码时,您会得到相同的输出。
2. Unicode字面量解读
但是,编码声明会影响 Python 如何解释使用 u-literals 声明的 unicode 字符串:
# -*- coding: utf-8 -*-
print repr(u'é') # u'\xe9'
# -*- coding: cp1252 -*-
print repr(u'é') # u'\xc3\xa9'
在最后一个示例中,Python 将u'é' 解释为
从\xc3\xa9 字节到cp1252 编码解码的unicode-string:
print repr(unicode('\xc3\xa9', 'cp1252')) # u'\xc3\xa9'
让我们打印这个 unicode 字符串:
print unicode('\xc3\xa9', 'cp1252') # é
因此,在源文件位于utf-8 且声明的编码为cp1252 的情况下,您可以使用é 的unicode-literal 获得é 输出:
# -*- coding: cp1252 -*-
print u'é' # é
有关更多信息,您可以查看以下内容:
PEP 263 -- Defining Python Source Code Encodings
The source of Python's tokenizer function