python之处理文件编码

0

Posted by conan | Posted in 总结 | Posted on 27-04-2010

做了手机天气预报和rss generator,有必要把处理字符串信息过程中遇到的问题总结一下了。

在做这两个东西的时候对python有了一些初步的理解,python用起来真的很舒服。数据结构,函数方法等都能够让你写出简短易读的代码。做天气预报的时候出现的问题比较简单,因为信息处理都是自己做的,只有发送的时候使用飞信库,所有抓取的信息甚至都不用解码,在程序里处理后直接发送出去就行,需要注意的就只有程序里写的字符要使用unicode,发送前进行编码就行了。做RSS生成的时候使用了PyRSS2Gen库,最后写入文件是使用此类库的函数进行的,在认知上出了点偏差,发生了不少的错误,饱受折磨好几天。

简而言之,把握住以下几点,在python中进行信息处理的时候应该不会再遇到这么多的信息编码问题。
1.在取得信息的时候(从文件,网络中)尽快进行解码,在程序中使用被解码的信息进行处理,在信息被写出去的时候(写到文件,网络等)再进行编码。
2.关于编码和解码,概念一度被我理解的比较混乱。首先是这个:

>>> “a”.decode(‘ascii’)
u’a’
>>> u’a’.encode(‘ascii’)
‘a’

这个到底怎么理解呢?我一直认为unicode和ascii是一个类别的,类似raw data的那一种,现在发现不对。因为unicode只是规定了字符集,但是没有规定存储方式,所以只有unicode是类似于raw数据的,它离开存储方式无法生存,而ascii则字符集和存储方式都有,所以说unicode可以作为一种内部数据处理方式,但是不能用来存储。所以,u’a'是unicode字符串,它被ascii进行编码之后出现ascii编码下的a,而’a'也可以被解码为unicode的字符串u’a'。于是在处理数据的时候,其实ascii是应该和utf-8,gb2312这种编码处于一个类别里。由于历史原因,ascii不管在什么地方都会获得良好的支持,所以ascii的信息不经过任何编码解码处理都不会有什么问题,而网络上编码千变万化,比如在中文互联网中gb2312和utf-8就经常相互打架。总结一下,编码和解码的过程应该这样处理,如果是ascii编码,完全不用理会编码解码的问题,而如果是utf-8或者gb2312这种,在取到的时候应当对其进行解码,这样数据就变成了unicode字符串,它适合在程序内部进行处理,在需要对其进行输出的时候,把它进行编码,需要utf-8的就编码为utf-8,需要gb2312的就编码为gb2312。

在rss生成的时候遇到的UnicodeDecodeError的问题,最后确认是因为对某些数据提前进行了encode操作,而写操作的时候依然需要进行encode操作。在python中,已编码的字符串也有encode方法,其操作是按照默认的ascii编码进行解码操作,然后再进行encode[2]。已编码为utf-8的字符是无法被ascii编码进行解码操作的,于是这个过程中就是把编码过的数据当作未编码的数据,试图对其进行解码导致了错误。参考如下,取自第二篇:

Why do Python byte strings have an encode() method?

The sharp-eyed amongst you will have noticed that byte strings have an encode() method as well as a decode() method. What does this do? Quite simply, it does a decode-then-encode. The byte string is decoded to Unicode using the default (ascii) encoding, and is then encoded to the target encoding specified in the call to encode() using the appropriate encoding. As you’d expect, fun and games ensue if the original byte string isn’t actually encoded in ASCII at all.

最终总结:对于python2.5而言,字符类型就两种,str和unicode[3],下图中左边是str,右边是unicode。
ascii—————–decode(‘ascii’)——-┐
utf-8—————–decode(‘utf-8′)——–┼—unicode
gb2312————decode(‘gb2312′)—┘

反之为encode操作。

参考:
1.python核心编程第二版
2.Python, Unicode and UnicodeDecodeError,地址在这里(英文,讲的很好)
3.Re: u’吴’和’吴’有什么区别? ,地址在这里