我还在学习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 编码,但它可以被标头声明覆盖,那么每个字符串声明的意义何在?
附录:似乎我把文件编码和字符串编码混在一起了。感谢您解释它:)
# coding: utf8
已经足够好了,不需要 -*-
# coding: utf-8
。
#coding=utf-8
。 python.org/dev/peps/pep-0263
正如其他人所提到的,这是两件不同的事情。
当您指定 # -*- 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'
,以声明一个字节序列)。
正如其他人所说,# 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 代码点,并且所有内容都打印不正确。
这并没有设置字符串的格式;它设置文件的格式。即使使用该标头,"hello"
也是字节字符串,而不是 Unicode 字符串。要使其成为 Unicode,您将不得不在任何地方使用 u"hello"
。标头只是提示在读取 .py
文件时使用什么格式。
标头定义是定义代码本身的编码,而不是运行时生成的字符串。
在没有 utf-8 标头定义的 python 脚本中放置像 2 这样的非 ascii 字符将引发警告
https://i.stack.imgur.com/Lr2qC.jpg
我制作了以下名为 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'>