首先要明确,string与unicode在python中的含义。
》》 string-escape是对二进制的字节流,一个字节一个字节转义,并对每个字节以16进制输出,比如:
In [22]: print "中".encode("string-escape")
\xe4\xb8\xad #注意,这是一个字符串
'\\xe4\\xb8\\xad'
这里是将"中"的utf-8编码值(
E4B8AD
)输出成一个可见字符串。
In [72]: "中".encode("string-escape")
Out[72]: '\\xe4\\xb8\\xad'
In [64]: u"中".encode("gbk").encode("string-escape")
Out[64]: '\\xd6\\xd0'
这里是将“中”以gbk编码之后的编码值输出。
》》 unicode-escape是对unicode编码的字节流,两个字节两个字节转义,并对每两个字节一起以16进制输出。
In [27]: print u"中".encode("unicode-escape")
\u4e2d
这里是将“中”的unicode编码值(
4E2D
)输出。
总结下:
unicode <-> utf8/gbk <-> string-escape
unicode <-> unicode-escape
对转义反斜线,两者的效果一样!
In [36]: print '\\\\u4e2d'.decode('unicode-escape')
\u4e2d
In [37]: print '\\\\u4e2d'.decode('string-escape')
\u4e2d
In [44]: print '\\\\xe4\\\\xb8\\\\xad'.decode('unicode-escape')
\xe4\xb8\xad
In [45]: print '\\\\xe4\\\\xb8\\\\xad'.decode('string-escape')
\xe4\xb8\xad
深刻理解这两个字符串的含义和区别:
In [76]: "\\x41\\x42\\x43\\xe4\\xb8\\xad"
Out[76]: '\\x41\\x42\\x43\\xe4\\xb8\\xad'
In [57]: len("\\x41\\x42\\x43\\xe4\\xb8\\xad")
Out[57]: 24
In [77]: "\x41\x42\x43\xe4\xb8\xad"
Out[77]: 'ABC\xe4\xb8\xad'
In [78]: len("\x41\x42\x43\xe4\xb8\xad")
Out[78]: 6
关于读文件:
如果文件中存储的内容是"
\x41\x42\x43\xe4\xb8\xad"
那么python程序去读到的是字符串其实是:
"\\x41\\x42\\x43\\xe4\\xb8\\xad"
In [57]: len("\\x41\\x42\\x43\\xe4\\xb8\\xad")
Out[57]: 24
也就是说,读到的内容,需要先decode("string-escape"),然后再decode("utf-8")
其他例子:
In [51]: "\x41\x42\x43\xe4\xb8\xad".decode('string-escape').decode('utf-8')
Out[51]: u'ABC\u4e2d'
In [55]: print "\\x41\\x42\\x43\\xe4\\xb8\\xad".decode('string-escape').decode('utf-8')
ABC中
In [79]: print "\x41\x42\x43\xe4\xb8\xad".decode("utf-8")
ABC中
附:编码相关知识
UNICODE 的范围是 0x0000 - 0xFFFF 共6万多个字符,其中光汉字就占用了4万多个
UTF-8 vs GBK:
UTF-8版本虽然具有良好的国际兼容性,但中文需要比GBK/BIG5版本多占用50%的数据库存储空间
,因此并非推荐使用,仅供对国际兼容性有特殊要求的用户使用。简单地说:对于中文较多的网站,适宜用GBK编码节省数据库空间。对于英文较多的网站,适宜用UTF-8节省数据库空间。
大部分是中文的同一份数据的空间占用示例:
-rw-rw-r-- 1 6372 May 27 14:01 gbk
-rw-rw-r-- 1 9204 May 27 14:01 utf-8