2007-07-16

 

Python Cookbook 2.10 处理内存中的zip文件

需求:

你的程序接收到一个字符串,里面包含了一个zip文件的内容,你需要获得这些信息.

讨论:

对于这一类问题,使用标准库的cStringIO最合适:

import cStringIO, zipfile
class ZipString(ZipFile):
    def _ _init_ _(self, datastring):
        ZipFile._ _init_ _(self, cStringIO.StringIO(datastring))

这样的问题会经常遇到,比如从数据库中的BLOB字段读取zip文件,或者从网络连接中读取.以前的时候,可以使用临时文件,用zipfile处理完数据后,要保证临时文件被删除;后来使用了cStringIO后,就再也没有使用过临时文件了.

cStringIO模块能够让你以文件的方式来访问字符串.另外,你也可以将数据以文件的方式写入cStringIO的实例,然后获得一个包含文件内容的字符串.大部分能处理file对象的Python模块并不检查你处理的对象是否真正是文件对象,只要是"类文件"对象就可以了.这些模块只是在需要的时候调用文件操作的方法,只要类文件对象提供类似的接口和适当的返回值,一切都没有问题.这就说明的多态的强大,以至于你几乎不需要写任何类型测试的代码(比如,if type(x) is y,或者if isinstance(x,y)).一些比较底层的模块,如marshl,需要使用真正的file对象,而zipfile是不需要的,所以我们的代码才能如此简单.
如果你使用的Python版本不是C语言版本,通常被成为"CPython",那你在标准库中可能没有cStringIO模块.以c开头的模块,暗示是以C语言实现的模块,它们能优化代码的效率,但是不保证所有的Python版本都通用.当然,一些别的版本的Python也提供了相关的模块.(如Jython,用java实现的版本并运行在jvm上,PyPy,用Python实现机器码,还有IronPython,用C#实现的,可以运行在.Net CLR环境里面).不用太担心,Python标准库总是提供了用标准Python实现的模块StringIO,它和cStringIO具有相同的实现(只是没有cStringIO效率高),你只需要修改import语句,让它能在cStringIO不存在的时候正确引用StringIO,比如:

import zipfile
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO
class ZipString(ZipFile):
    def _ _init_ _(self, datastring):
        ZipFile._ _init_ _(self, StringIO(datastring))

这样修改的话,本节的代码就能在Jython或者其它版本的Python中运行了.

相关说明:

StringIO(...)
    StringIO([s]) -- Return a StringIO-like stream for reading or writing


Comments: 发表评论



<< Home

This page is powered by Blogger. Isn't yours?