一、编码
(1)
python中,字符集的处理的两个对象:
str 是指带有编码的字符串
unicode 是指不带有编码的字符串
相互转换:
str ------> unicode --------> str
decode encode
解码 编码
1 | >>> a = '中' |
2 | >>> a |
3 | '/xd6/xd0' |
4 | >>> b = u'中' |
5 | >>> b |
6 | u'/u4e2d' |
7 | |
8 | #根据上面的描述,b应该是不进行编码的a的值(反正a就是b带有gbk编码的值) |
9 | >>> a.decode( 'gbk' ) |
10 | u'/u4e2d' |
11 | |
12 | #同样也可以得到 |
13 | >>> b.encode( 'gbk' ) |
14 | '/xd6/xd0' |
(2)xml文件的编码
python的xml模块只支持utf-8编码,因为xml的标准规范仅仅定义了utf-8做为多字节xml的编码,gbk(gb2312)并不是xml规范中允 许的字符集。
解决办法一:
在处理gbk编码集的xml时,都是先将文件读取出来,然后转换为utf8格式,然后再解析。
1 | >>> f = file( r'c:/a.xml' ) |
2 | >>> buf = f.read() |
3 | >>> ubuf = buf.decode( 'gbk' ).encode( 'utf-8' ) |
4 | >>> xml.parser( ubuf ) |
5 | ... |
6 |
调用字符串的decode和encode方法有一个好处是,不用显式import codecs模块,更不用lookup特定字符编码的decode和encode函数。但是这种方法不适用于对decode和encode方法多次重复调用的场合,主要是从代码的执行效率方面考虑的。
解决办法二:
将xml文件转换成UTF-8,读出文件转换后回写。
1 | import codecs |
2 | f = codecs.open(‘D://normal.txt’, ‘rb’, ‘mbcs’) |
3 | text = f.read().encode(‘utf-8′) |
4 | f.close |
5 | f = open(‘d://utf8.txt’, ‘wb’) |
6 | f.write(text) |
7 | f.close() |
8 | print text.decode(‘utf-8′).encode(‘gb2312′) |
9 |
解决办法三:
xml文件里面不要写入encoding,保持为gb2312本地编码,然后程序解析的时候,采用语句
1 | unicode(file('f://temp//a.txt', 'r', 'gb2312').read(),'gb2312').encode('utf-8') |
将整个文件转成utf-8的 String 来处理,处理结束后,利用
1 | unicode(string,'utf-8').encode('gb2312') |
换成本地的gb码,再将结果写回文件。
二、用codecs模块完成字符编码
字符的编码是按照某种规则在单字节字符和多字节字符之间进行转换的某种方法。从单字节到多字节叫做decoding,从多字节到单字节叫做encoding。在这些规则中经常用到的无非是UTF-8和GB2312两种。
在Python中,codecs模块提供了实现这些规则的方法,通过模块公开的方法我们能够方便地获取某种编码方式的Encoder和 Decoder工厂函数(Factory function),以及StreamReader、StreamWriter和StreamReaderWriter类。
使用“import codecs”导入codecs模块。codecs模块中重要的函数之一是lookup,它只有一个参数encoding,指的是编码方式的名称,即utf-8或者gb2312等等。如下示例:
1 | >>> import codecs |
2 | >>> t = codecs.lookup("utf-8") |
3 | >>> print t |
4 | (<built-in function utf_8_encode>, <function decode at 0x00AA25B0>, <class encodings.utf_8.StreamReader at 0x00AA0720>, <class encodings.utf_8.StreamWriter at 0x00AA06F0>) |
5 | >>> encoder = t[0] |
6 | >>> decoder = t[1] |
7 | >>> StreamReader = t[2] |
8 | >>> StreamWriter = t[3] |
9 |
lookup函数返回一个包含四个元素的TUPLE,其中T[0]是encoder的函数引用,T[1]是 decoder的函数引用,T[2] 是UTF-8编码方式的StreamReader类对象引用,T[3]是UTF-8编码方式的StreamWriter类对象引用相信对Python熟悉的你肯定知道接下来该怎么用它们了。
codecs模块还提供了方便程序员使用的单独函数,以简化对lookup的调用。它们是:
- getencoder(encoding)
- getdecoder(encoding)
- getreader(encoding)
- getwriter(encoding)
如果我们只是想获取一种utf-8编码的encoder方法,那么只需要这样做:
>>> encoder = codecs.getencoder("utf-8")
另外,对于StreamReader和StreamWriter的简化, codecs模块提供一个open方法。相对于built-in对象File的open方法,前者多了三个参数encoding, errors, buffering。这三个参数都是可选参数,但是对于应用来说,需要明确指定encoding的值,而errors和buffering使用默认值即可。使用方法如下:
1 | >>> fin = codecs.open("e://mycomputer.txt", "r", "utf-8") |
2 | >>> print fin.readline() |
3 | 这是我的电脑 |
4 | |
5 | >>> fin.close() |
总结一下,codecs模块为我们解决的字符编码的处理提供了lookup方法,它接受一个字符编码名称的参数,并返回指定字符编码对应的 encoder、decoder、StreamReader和StreamWriter的函数对象和类对象的引用。为了简化对lookup方法的调用, codecs还提供了getencoder(encoding)、getdecoder(encoding)、getreader(encoding)和 getwriter(encoding)方法;进一步,简化对特定字符编码的StreamReader、StreamWriter和 StreamReaderWriter的访问,codecs更直接地提供了open方法,通过encoding参数传递字符编码名称,即可获得对 encoder和decoder的双向服务。
-----------------------------------------------
PS:对Python里面的编码总算有个比较清楚的认识了,为了避免麻烦,自己写程序好文件的时候,都在前面加上# -*- coding: utf-8 -*-为好。
用C扩展Python,在Python里面传一个字符串给C,在C中打印,如果其中有中文字符,就会有乱码。(如果你没有在文件中加# -*- coding: utf-8 -*-,就不会有这个问题)
解决方法如下:
s = u"欢迎使用rss阅读器"
s=s.encode('gbk')
libConsole.ConsoleOutput(s) # libConsole是用C封装成的一个dll,
# ConsoleOutput(s) 是用C写的一个方法,就是