Python Cookbook-2.10 处理字符串中的 zip 文件

任务

程序接收到了一个字符串,其内容是一个 zip 文件,需要读取这个 zip 文件中的信息。

解决方案

应对这种问题,采用Python标准库的cStringIO 模块的拿手好戏:

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

讨论

在遇到这类任务–比如 zip 文件可能来自于数据库的 BLOB 字段,或者来自于网络连接。过去把这些二进制数据先存成临时文件,然后用标准库模块 zipfile 打开此文件。当然,会确保完成任务之后删除临时文件。一天,想到了使用标准库模块 cStringI,之后就再也没用过老办法了。

cStringIO 模块可以将一串字节封装起来,让你像访问文件对象一样访问其中的数据另一方面,还可以用把 cStringlO.StringIO 的实例当做一个文件对象,向其中写入数据最后得到的是一串内存中的字节。很多处理文件的Python 模块其实根本不检查你传递给它们的是不是一个真正的文件——任何像文件一样的对象它们都接受。它们只是在需要的时候调用文件的方法,只要给这些对象提供了相关的方法,并且做出了正确的反应,一切都会正常工作。这展示了基于签名的多态机制的强大力量,同时也解释了为什么最好不要在你的代码中进行类型检查(比如可怕的if type(x) is y,以及稍微好点的 if isinstance(x,y)。一些低级的模块,比如 marshal,很不幸地会执着要求“真实的文件,但 zipfile 很通融,本节的例子也说明了,有了它生活多么美好。

如果用的 Python版本和主流的基于C的Python版本(也称为 CPython)不同,可能在标准库中找不到 cStringIO 模块。模块名最前面的c,表示它是个基于C的模块,为速度做过优化,不保证能够在其他兼容的Python 实现体的标准库中找到对应的版本。这些兼容的 Python 实现体包括了产品级品质的(比如Jython,用Java实现并运行在JVM上)以及实验性的(比如 pypy,用Python 代码产生机器码结果,以及IronPython,基于 C#并运行在微软的.NET CLR)。别担心,Python 标准库总会包含 StringI0 模块,它由纯Python代码实现(因此也能适用于任何兼容的Python实现体),并实现了和cStringIO 一样的功能(不过没有那么快,至少在主流的 CPython 上是这样)。只需略微修改一下 import 语句,以确保如果有 cStringIO,就导入 cStringIO,如果没有,则导人StringIO作为代替。比如,代码可能会变成这样:

import zipfile
try:
	from cStringIO importstringIO
except ImportError:
	from StringIO import StringIO
class ZipString(ZipFile):
	def __init__(self,datastring):
		ZipFile.__init__(self,stringIO(datastring))

经过这次修改,这段代码就可以在Jython 或其他的实现体中工作了

你可能感兴趣的:(#Python学习,python,开发语言)