2012-08-16 149 views
5

显然,我能做到这一点在Python 2.7:字节字符串字面与非ASCII字符

value = '國華' 

好像Python是用编码来编码字符的字符串字面量为字节的字符串中。什么是编码?那是sys.getdefaultencoding()中定义的编码,源文件的编码还是别的?

感谢

+1

源文件或命令行中是否存在该行?另外,你是否真的想学习Python 2.7中编码的复杂性(与2.6和3.x稍有不同),还是只是想解决一个可以通过在前面粘贴'u'解决的问题报价? – abarnert 2012-08-16 18:33:43

+0

我其实正在尝试学习Python 2.7编码的复杂性。这是在一个源文件中,但我也有兴趣知道在命令提示符下这是不同的。 – Flavien 2012-08-16 19:25:06

+1

Python 2.7表示不这样做,但如果您对CPython 2.7所做的事情感兴趣,无论如何......源文件中引号内的字面字节(例如'\ xe5 \ x9c \ x8b \ xe8 \ x8f \ xaf')被存储为一个字节字符串。由于源文件的编码声明可能与'sys.getdefaultencoding()'不同,因此您可能无法安全地解释它,但字节在那里。如果两种编码是相同的,终端也是如此,并且编码可以处理这些字符,那么甚至可以“打印价值”并查看您的期望。这是你想要的,还是有更多? – abarnert 2012-08-16 20:48:07

回答

7

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

Python的2.X,你在没有声明编码的脚本代码行产生一个错误:

SyntaxError: Non-ASCII character '\x87' in file ... 

实际的非ASCII字符可能会有所不同,但不会没有编码工作宣言。编码声明要求在Python 2.X上使用非ASCII字符。编码声明必须匹配源文件的编码。例如:

# coding: utf8 
value = '國華' 

当保存为CP936产生:

SyntaxError: 'utf8' codec can't decode byte 0x87 in position 9: invalid start byte 

当编码是正确的,该字节串中的字节是字面上是源文件中,所以它将包含编码字符的字节。当Python解析一个Unicode字符串时,这些字节会使用声明的源编码解码为Unicode。注意区别打印UTF-8字节串和CP936控制台上的Unicode字符串时:

# coding: utf8 
value = '國華' 
print value,repr(value) 
value = u'國華' 
print value,repr(value) 

输出:

鍦嬭彲 '\xe5\x9c\x8b\xe8\x8f\xaf' 
國華 u'\u570b\u83ef' 

字节字符串包含3字节的UTF-8编码的两个字符,但由于cp936终端无法理解字节序列,所以显示不正确。 Unicode打印正确,并且该字符串包含从源文件的UTF-8字节解码的Unicode代码点。

注声明和使用该终端相匹配的编码时的区别:

# coding: cp936 
value = '國華' 
print value,repr(value) 
value = u'國華' 
print value,repr(value) 

输出:

國華 '\x87\xf8\xc8A' 
國華 u'\u570b\u83ef' 

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

如果脚本具有正确的源编码声明和使用Unicode字符串为文本,它将显示正确的字符终端编码无关。如果终端不支持字符而不是显示错误的字符,它会抛出UnicodeEncodeError

最后说明:Python 2.X默认为'ascii'编码,除非另有声明,并且如果编码支持它们,则字节字符串中允许使用非ASCII字符。 Python 3.X默认使用'utf8'编码(所以请确保保存在该编码中或另外声明),并且而不是允许在字节字符串中使用非ASCII字符。

如果终端字体支持字符。
如果终端编码支持字符。

1
value = b'國華' 

是没有意义的(在b在Python 2.x的是隐含的) - 你为什么要一个字节字符串包含字符? Python可以简单地复制终端/编辑器使用的任何编码字节。你想要的是一个字符字符串:

value = u'國華' 

在源代码文件(而不是一个交互式shell),不通过将下面的行添加到文件的开头忘记declare the encoding

# -*- coding: utf-8 -*- 
+0

很明显,Python设计师并不认为这是毫无意义的,因为他们认为它是有效的。你没有真正回答我的问题,当我运行该行时,Python使用哪种编码,我如何从代码中找出问题? – Flavien 2012-08-16 19:28:54

+0

当您在交互式shell或具有编码声明的源文件中运行该行时,或者...什么? – abarnert 2012-08-16 19:38:27

+2

@字节文字中的@Flavien非ASCII字符是历史文物。没有使它们有效的代码,它们只是被意外接受,并且可以追溯到Python没有明确字节与字符串语义的时间。字节文字中的非ASCII字符不再有效;他们已经[从Python 3中移除](http://ideone.com/f1iLN)。运行该行时,Python不使用任何编码。该文件是一串字节,字面值产生的字节对象也是如此。 – phihag 2012-08-16 19:56:10