具有非ascii字符的字节字符串文字

Fla*_*ien 6 python unicode encoding internationalization

显然,我可以在Python 2.7中做到这一点:

value = '??'
Run Code Online (Sandbox Code Playgroud)

似乎Python正在使用编码将字符串文字中的字符编码为字节字符串.什么是编码?这是sys.getdefaultencoding()源文件的编码,或其他什么定义的编码?

谢谢

Mar*_*nen 7

getdefaultencoding与源文件或终端的编码无关.它是用于将字节字符串隐式转换为Unicode字符串的编码,在Python 2.X(Python 3.X上的'utf8')中应始终为'ascii'.

在Python 2.X上,未声明编码的脚本中的代码行会产生错误:

SyntaxError: Non-ASCII character '\x87' in file ...
Run Code Online (Sandbox Code Playgroud)

实际的非ASCII字符可能会有所不同,但如果没有编码声明,它将无法工作.在Python 2.X上使用非ASCII字符需要编码声明.编码声明必须与源文件编码匹配.例如:

# coding: utf8
value = '??'
Run Code Online (Sandbox Code Playgroud)

当保存为cp936时产生:

SyntaxError: 'utf8' codec can't decode byte 0x87 in position 9: invalid start byte
Run Code Online (Sandbox Code Playgroud)

当编码正确时,字节字符串中的字节实际上是源文件中的字节,因此它将包含字符的编码字节.当Python解析Unicode字符串时,使用声明的源编码将字节解码为Unicode.请注意在cp936控制台上打印UTF-8字节字符串和Unicode字符串时的区别:

# coding: utf8
value = '??'
print value,repr(value)
value = u'??'
print value,repr(value)
Run Code Online (Sandbox Code Playgroud)

输出:

??? '\xe5\x9c\x8b\xe8\x8f\xaf'
?? u'\u570b\u83ef'
Run Code Online (Sandbox Code Playgroud)

字节字符串包含两个字符的3字节UTF-8编码,但显示不正确,因为cp936终端无法理解字节序列.Unicode打印正确,字符串包含从源文件的UTF-8字节解码的Unicode代码点.

请注意声明和使用与终端匹配的编码时的区别:

# coding: cp936
value = '??'
print value,repr(value)
value = u'??'
print value,repr(value)
Run Code Online (Sandbox Code Playgroud)

输出:

?? '\x87\xf8\xc8A'
?? u'\u570b\u83ef'
Run Code Online (Sandbox Code Playgroud)

字节串的内容现在是两个字符的2字节cp936编码('A'相当于'\ x41'),并且由于终端理解cp936字节序列而正确显示.Unicode字符串包含与前一示例相同的两个字符的Unicode代码点,因为源字节序列使用声明的源编码解码为Unicode.

如果脚本具有正确的源编码声明并使用Unicode字符串作为文本,则无论终端编码2如何,它都将显示正确的字符1.如果终端不支持该字符而不是显示错误的字符,它将抛出一个.UnicodeEncodeError

最后一点:Python 2.X默认为'ascii'编码,除非另有声明,如果编码支持,则允许字节字符串中的非ASCII字符.Python的3.X默认为"utf-8"编码(所以一定要确保在编码格式来储存或以其他方式申报),并没有容许在字节串非ASCII字符.

1如果终端字体支持该字符.
2如果终端编码支持该字符.