Why declare unicode by string in python?

I'm still learning python and I have a doubt:

In python 2.6.x I usually declare encoding in the file header like this (as in PEP 0263)

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

After that, my strings are written as usual:

a = "A normal string without declared Unicode"

But everytime I see a python project code, the encoding is not declared at the header. Instead, it is declared at every string like this:

a = u"A string with declared Unicode"

What's the difference? What's the purpose of this? I know Python 2.6.x sets ASCII encoding by default, but it can be overriden by the header declaration, so what's the point of per string declaration?

Addendum: Seems that I've mixed up file encoding with string encoding. Thanks for explaining it :)

166535 次浏览

它不设置字符串的格式; 它设置文件的格式。即使有了这个头,"hello"也是一个字节字符串,而不是 Unicode 字符串。要使其成为 Unicode,您必须在任何地方都使用 u"hello"。标头只是读取 .py文件时使用什么格式的提示。

头定义是定义代码本身的编码,而不是在运行时定义结果字符串。

如果没有 utf-8头文件定义,就像在 python 脚本中放入一个非 ascii 字符,那么将抛出一个警告

error

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

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

一般来说,不管编码是什么,在文件中嵌入高 Unicode 字符可能都不是一个好主意; 您可以使用字符串 unicode 转义,它可以在任何编码中工作。


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

这只适用于 Python2; 在 Python3中,默认值是 Unicode,并且需要在前面指定 b(如 b'These are bytes',以声明字节序列)。

正如其他人所说,# 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 + 00 FC。当打印字节字符串时,Python 将十六进制值 81直接发送到控制台。打印 Unicode 字符串时,Python 正确地检测到控制台编码为 cp437,并将 Unicode 翻译转换为 翻译的 cp437值。

下面是用 UTF-8声明和保存的文件:

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

In UTF-8, 翻译 is encoded as the hex bytes C3 BC, so the byte string contains those bytes, but the Unicode string is identical to the first example. Python read the two bytes and decoded it correctly. Python printed the byte string incorrectly, because it sent the two UTF-8 bytes representing 翻译 directly to my cp437 console.

这里的文件声明为 cp437,但保存为 UTF-8:

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

字节字符串仍然获取磁盘上的字节(UTF-8十六进制字节 C3 BC) ,但是将它们解释为两个 cp437字符,而不是一个 UTF-8编码的字符。这两个字符在转换为 Unicode 代码点时,所有输出都不正确。

为了能够对变量进行转换,我制作了下面这个叫做 unicorder 的模块:

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'>