如果把str也视为一个数组,那么它的每个元素都是8-bit的。
(文档中有句话,“Another important method is .encode([encoding], [errors=’strict’]), which returns an 8-bit string version of the Unicode string”。
type(u'abc'.encode('utf8'))的值是<type 'str'>,所以可以推断出str是个8-bit string。)
Software should only work with Unicode strings internally, converting to a particular encoding on output.
程序内部使用unicode类型。输出时再做转换(不一定要自己转,比如可以借助codecs)。
Include characters > 127 and, even better, characters > 255 in your test data.
测试的时候,使用unicode字符(大于255的code point)。
import unicodedata
u = unichr(233) + unichr(0x0bf2) + unichr(3972) + unichr(6000) + unichr(13231)
for i, c in enumerate(u):
print i, '%04x' % ord(c), unicodedata.category(c),
print unicodedata.name(c)
Encode后的字符串可能会面目全非,比如,
def read_file (filename, encoding):
if '/' in filename:
raise ValueError("'/' not allowed in filenames")
unicode_name = filename.decode(encoding)
f = open(unicode_name, 'r')
# ... return contents of file ...
Python and Unicode
Python官网上有篇文档,Unicode HOWTO,对怎么在Python中处理Unicode做了详细的介绍。下面是这篇文档的一个简单笔记。
Unicode的相关概念
Unicode为世界上的每个字符都分配了一个数值,这个数值叫做
code point
。code point
通常以16进制表示,比如U+12ca
,表示值为4810
(16进制0x12ca
)的code point。Code point只是个整数值,而数据在计算机内部是以二进制表示的;把code point以某种方式映射成二进制数据就叫encoding。 例如一种encoding可以把每个code point表示成两个byte(虽然两个byte不能表示所有的unicode字符)。
UTF-8
是一种常用的encoding,它是一种“变长”的encoding,不同的code point可能占用不同长度的byte。 UTF-8可以表示所有的code point。Python支持近100种encoding,这里有详细的列表。 一些encoding可能有多个名字,比如
utf-8
,utf_8
,U8
,UTF
,utf8
都是指同一种encoding。 Python默认的encoding是ascii
。默认情况下,如果Python发现字符串中的某些字符不能被ascii
表示,就会抛一个UnicodeEncodeError
异常。Python中的字符串
Python里有两种类型的字符串,一种是
str
类型,一种是unicode
类型。 两者的基类都是basestring
;所以可以通过isinstance(value, basestring)
来判断一个value是不是字符串。unicode
字符串字符串可以理解成数组;
unicode
类型的字符串可以理解为元素为整数(code point的值)的数组。 在Python内部,unicode
字符串的元素以16位或者32位整数来表示(取决于Python解释器是怎么编译的)。构造函数
unicode(string[, encoding, errors])
可以用来生成unicode
字符串。 它的所有参数都是8-bit strings。unichr()
可以接收一个整数(code point),生成一个长度为1的unicode
字符串。ord()
则接收一个长度为1的unicode
字符串,返回它的code point。unicode
有着和str
类似的方法。str
字符串如果把
str
也视为一个数组,那么它的每个元素都是8-bit的。 (文档中有句话,“Another important method is .encode([encoding], [errors=’strict’]), which returns an 8-bit string version of the Unicode string”。type(u'abc'.encode('utf8'))
的值是<type 'str'>
,所以可以推断出str
是个8-bit string。)str
和unicode
可以通过.encode([encoding], [errors='strict'])
和.decode([encoding], [errors])
函数互相转换。Python源文件和unicode
如果想在Python源文件中表示一个
unicode
字符串(unicode literals),可以这样,上面的方式比较繁琐。可以在Python源文件里声明源文件的encoding,然后就可以“自然语言”来声明unicode literals了。
输入和输出
把输入转换为unicode,内部以unicode处理,再把unicode以某种encoding输出(比如写文件)。
如果输入输出时使用到了某些库,而这些库本身就支持unicode,那么开发时就不需要自己写unicode转换相关的代码。 比如一些XML parsers常常会返回unicode形式的数据;那么,这些XML parsers的用户就不用再去关心怎么把输入转成unicode了。
输出时,一般要先把unicode以某种方式encoding,然后再输出。 不推荐自己来做这种工作。Python有
codecs
库帮你做这些工作。codecs
提供了open()
函数,可以返回一个file-like object。unicode和文件名
很多操作系统都支持文件名中带有任意的unicode字符。但是不同系统采用的encoding可能不太一样。 比如OS X用UTF-8,Windows支持用户配置的encoding,Unix看
LANG
或者LC_CTYPE
环境变量。一般来说,在Python程序中不需要关心上面这些细节。
建议
文档里给出了两个建议。
unicode
类型。输出时再做转换(不一定要自己转,比如可以借助codecs
)。其它
Unicode规范还包括一个database,里面有每个code point相关的信息,比如name,category等。
Encode后的字符串可能会面目全非,比如,
这段代码的功能是检测’/’字符。例如,如果filename参数是’/etc/passwd’时,就会报错。 但是如果filename是经过
base64
编码的,那么’/etc/passwd’会被encode成’L2V0Yy9wYXNzd2Q=’,上面这段代码就会失效。根据这篇文章的观点,Python 2的
str/unicode
存在的问题是设计Python 3的重要原因。如果你觉得这篇文章对你有用,可以微信扫一扫表示🙏 / If you find this post is useful to you, buy me 🍶 via Wechat