为什么在python中用字符串声明unicode?

时间:2010-07-03 03:28:15

标签: python encoding utf-8

我还在学习python,我有一个疑问:

在python 2.6.x中,我通常在文件头中声明编码,如下所示(如PEP 0263中所示)

# -*- coding: utf-8 -*-

之后,我的字符串照常编写:

a = "A normal string without declared Unicode"

但是每当我看到python项目代码时,编码都不会在标头处声明。相反,它在每个字符串声明如下:

a = u"A string with declared Unicode"

有什么区别?这是为了什么目的?我知道Python 2.6.x默认设置ASCII编码,但它可以被头声明覆盖,那么每个字符串声明的重点是什么?

附录:似乎我已将文件编码与字符串编码混合在一起。谢谢你解释一下:)

5 个答案:

答案 0 :(得分:157)

正如其他人所提到的那样,这是两件不同的事情。

当您指定# -*- coding: utf-8 -*- 时,您告诉Python您保存的源文件是utf-8。 Python 2的默认值是ASCII(对于Python 3,它是utf-8)。这只会影响解释器读取文件中字符的方式。

通常,无论编码是什么,将高unicode字符嵌入到文件中可能不是最佳选择;你可以使用字符串unicode转义,它可以在任何一种编码中使用。


当声明前面带有u的字符串时,如u'This is a string',它告诉Python编译器字符串是Unicode,而不是字节。这主要由翻译人员透明地处理;最明显的区别是你现在可以在字符串中嵌入unicode字符(也就是说,u'\u2665'现在是合法的)。您可以使用from __future__ import unicode_literals将其设为默认值。

这仅适用于Python 2;在Python 3中,默认值是Unicode,您需要在前面指定b(如b'These are bytes',以声明一个字节序列)。

答案 1 :(得分:22)

正如其他人所说,# coding:指定保存源文件的编码。以下是一些例子来说明这一点:

以cp437(我的控制台编码)保存在磁盘上的文件,但未声明编码

b = 'über'
u = u'über'
print b,repr(b)
print u,repr(u)

<强>输出:

  File "C:\ex.py", line 1
SyntaxError: Non-ASCII character '\x81' in file C:\ex.py on line 1, but no
encoding declared; see http://www.python.org/peps/pep-0263.html for details

添加了# coding: cp437的文件输出:

über '\x81ber'
über u'\xfcber'

起初,Python不知道编码并且抱怨非ASCII字符。一旦知道编码,字节字符串就会获得实际存在于磁盘上的字节。对于Unicode字符串,Python读取\ x81,知道在cp437中是ü,并将其解码为ü的Unicode代码点,即U + 00FC。打印字节字符串时,Python直接将十六进制值81发送到控制台。打印Unicode字符串时,Python正确检测到我的控制台编码为cp437,并将Unicode ü转换为ü的cp437值。

以下是以UTF-8声明并保存的文件:

├╝ber '\xc3\xbcber'
über u'\xfcber'

在UTF-8中,ü被编码为十六进制字节C3 BC,因此字节字符串包含这些字节,但Unicode字符串与第一个示例相同。 Python读取两个字节并正确解码。 Python错误地打印了字节字符串,因为它将表示ü的两个UTF-8字节直接发送到我的cp437控制台。

此处文件声明为cp437,但以UTF-8保存:

├╝ber '\xc3\xbcber'
├╝ber u'\u251c\u255dber'

字节字符串仍然获取磁盘上的字节(UTF-8十六进制字节C3 BC),但将它们解释为两个cp437字符而不是一个UTF-8编码字符。这两个字符转换为Unicode代码点,并且所有内容都打印错误。

答案 2 :(得分:10)

不设置字符串的格式;它设置文件的格式。即使使用该标头,"hello"也是字节字符串,而不是Unicode字符串。要使其成为Unicode,您将不得不在任何地方使用u"hello"。标题只是提示在阅读.py文件时使用的格式。

答案 3 :(得分:7)

标头定义用于定义代码本身的编码,而不是运行时生成的字符串。

在没有utf-8标头定义的python脚本中放置非ascii字符(如2)会发出警告error http://www.freeimagehosting.net/uploads/1ed15124c4.jpg

答案 4 :(得分:-1)

我制作了以下名为unicoder的模块,以便能够对变量进行转换:

import sys
import os

def ustr(string):

    string = 'u"%s"'%string

    with open('_unicoder.py', 'w') as script:

        script.write('# -*- coding: utf-8 -*-\n')
        script.write('_ustr = %s'%string)

    import _unicoder
    value = _unicoder._ustr

    del _unicoder
    del sys.modules['_unicoder']

    os.system('del _unicoder.py')
    os.system('del _unicoder.pyc')

    return value

然后在您的程序中,您可以执行以下操作:

# -*- coding: utf-8 -*-

from unicoder import ustr

txt = 'Hello, Unicode World'
txt = ustr(txt)

print type(txt) # <type 'unicode'>