[大数据处理]Python直接操作压缩包里面的文件

大数据处理中,常常会遇到压缩后的数据包,比如BZ2,ZIP等格式,这里简单的介绍了Python在无解压的情况下读取BZ2压缩文件,另外通过lxml中iterparse()的对于XML大型文件处理的方法。

大数据处理中,常常会遇到压缩后的数据包,比如BZ2,ZIP等格式,这里简单的介绍了Python在无解压的情况下读取BZ2压缩文件,另外通过lxml中iterparse()的对于XML大型文件处理的方法。

在处理维基百科的DUMP包的时候,会遇到一个问题:大数据,几乎每一个DUMP在解压后都有400-500GB,没有解压之前如果是BZ2格式的话,大小也在20-30GB之间。
对于大数据的一般处理顺序:解压压缩包,再处理。可是把所有压缩包解压,可能没有足够的硬盘空间, 而且也很费时间。那么就试试不解压的情况下来操作,整个过程都在Python 2.7.*的环境下运行。

BZ2文件:

#加载bz2模块
from bz2 import BZ2File as b2f

fp = b2f("filename.bz2") #filename.bz2是要处理的压缩包名字
line = fp.readline() #读取一行
while line: #按行读取,并自动读完的时候停止
    print line
    line = fp.readline()

现在我们知道了如何在不解压的情况下处理bz2格式的文件,那么维基百科提供的DUMP都按照BZ2格式的压缩,而且里面的文件是XML文件,那么该如何处理维基百科的数据呢?
Python提供了xml.sax来处理XML大型文件,而且这个处理方式完全可以和上面的方式联合来直接操作20几个GB的数据包。这里就介绍一下操作方式,下面这段SAX代码引子别处,并且在上面做了一些修改, 源代码网址:http://my.oschina.net/renhc/blog/59646

from bz2 import BZ2File as b2f #加载bz2模块
from xml.sax import parse, handler, SAXException

class MyXMLSAXHandler(handler.ContentHandler):
    """
    用户自定义事件处理器
    """
    #文档开始事件处理
    def startDocument(self):
        print 'Document Start...'
 
    #文档结束事件处理
    def endDocument(self):
        print 'Document End...'
 
    #元素开始事件处理
    #"name"是节点名称,"attrs"是节点属性
    def startElement(self, name, attrs):
        print 'encounter element(%s)' % (name)
 
    #元素结束事件处理
    def endElement(self, name):
        print 'leave element(%s)' % (name)
    #内容事件处理
    def characters(self, content):
        if content.isspace():  #去掉内容中的空格
            return
        print 'characters:' + content

try:
    fp = b2f("filename.bz2","r") #filename.bz2是要处理的压缩包名字
    parse(fp, MyXMLSAXHandler())
except SAXException, msg:
    print msg.getException()
except:
    print sys.exc_info()[0],sys.exc_info()[1]

这段代码其实不难理解,类MyXMLSAXHander继承了handler.ContentHandler, 在parse()分析XML文件是,从头到尾像流水一下的处理文件,类似与逐行读取,并在读取到相应的节点的时候,进行相关处理。
也许通过xml.sax来控制数据还是比较复杂且花费时间,那么可以试试lxml中提供的iterparse(),这个方法基于SAX,操作大型数据就变的简单多了,类似的Python自身也提供了iterparse()模块, 有兴趣的可以移步:
http://docs.python.org/2/library/xml.etree.elementtree.html#xml.etree.ElementTree.iterparse, 小提示:xml.etree.ElementTree和xml.etree.cElementTree都可以用哦,后者基于C的模块,速度会更快一些。 废话不多说,直接进入lxml.etree.iterparse()的用法,后面清除内存的那块一定得加。

from bz2 import BZ2File as b2f
from lxml import etree

f1 = "filename.xml.bz2"
fp = b2f(f1,"r")
node_find = "page" #要寻找的节点的名字

#fp上面的传送过来的一个Objet, 其实也可以是一个文件名。
#end是某个节点的结尾
tree = etree.iterparse(fp,events=("end",), tag=node_find)
for event, elem in tree:
    #输出结果
    print etree.tostring(elem, encoding="utf-8", pretty_print=True,
                xml_declaration=True)

    #清除内存
    elem.clear() 
    while elem.getprevious() is not None:
        del elem.getparent()[0]

好了,就到这里,如问题请留言。

Ubuntu安装lxml

lxml作为python处理xml文本的模块,文档开发的十分完善,个人非常推荐,以下是在ubuntu下的安装方式:

由于lxml需要libxml2-dev和libxslt-dev两个模块支持,所以需要先安装这两个模块,

apt-get install libxml2-dev libxslt-dev

之后安装lxml
apt-get install python-lxml

Python中def的内存处理

python def定义了一个方法(函数/模块),他们的内存使用方式很简单,调用完就清楚内存,但是有特别的情况比如调用模块libxml2。

python在通过def定义了一个方法后,每次调用这个模块,都将进行内存加载。但是一旦使用完整个方法并返回后,python的内存管理机制,将会自动将所有的内存清空。网上已经有很多文章讲解内存管理机制,因此这里就简单的引用一下别人的文章,做个记录。

关于Python的内存管理机制,这里引用51cto的一篇文章中提到的:
“在Python中,许多时候申请的内存都是小块的内存,这些小块内存在申请后,很快又会被释放,由于这些内存的申请并不是为了创建对象,所以并没有对象一级的内存池机制。
这就意味着Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。这也就是之前提到的Pymalloc机制。
在Python 2.5中,Python内部默认的小块内存与大块内存的分界点定在256个字节,这个分界点由前面我们看到的名为SMALL_REQUEST_THRESHOLD的符号控制。
也就是说,当申请的内存小于256字节时,PyObject_Malloc会在内存池中申请内存;当申请的内存大于256字节时,PyObject_Malloc的行为将蜕化为malloc的行为。当然,通过修改Python源代码,我们可以改变这个默认值,从而改变Python的默认内存管理行为。
在一个对象的引用计数减为0时,与该对象对应的析构函数就会被调用。”

引用地址:
http://developer.51cto.com/art/201007/213585.htm

Python模块libxml2

libxml2是一个很强大的处理XML文件的Python模块,通过C写成,这里介绍了一下基本的资料,安装,下载和基本指令,还有一个libxml2造成的内存泄露的处理方式。

libxml2是一个很强大的处理XML文件的Python模块,通过C写成,这里介绍了一下基本的资料,安装,下载和基本指令,还有一个libxml2造成的内存泄露的处理方式。

官方网址:
http://xmlsoft.org/
具体的下载地址,埋的很深,至少我花了一段时间才找到,这里直接给出win32下的Python模块下载地址:
http://xmlsoft.org/sources/win32/python/
根据自己的Python版本下载就行。

官方网站上给的操作信息是在少的可怜,只有单单一页的Python API介绍
http://xmlsoft.org/python.html

后来找了一些大神的博客才算零零碎碎的筹齐需要的知识点:
XPath (libxml2) in Python
http://ukchill.com/technology/getting-started-with-libxml2-and-python-part-1/
http://ukchill.com/technology/getting-started-with-libxml2-and-python-part-2/

这几就介绍一下最简单的操作:

import libxml2
doc = libxml2.parseFile(filename) #可以使用parseDoc代替parseFile,两者的区别是DOC处理已经读进进程的文件,File是能自己读取文件,所以只需要提供文件名。
ctxt = doc.xpathNewContext()
record_nodes = ctxt.xpathEval('/*') #括号中的XPATH,这是寻找的是根目录下的所有NODE。 xpathEval寻找结果给出的是一个x列表,如xrange(10)生成的内容。
for node in record_nodes:
    name = node.name #node的名字
    content = node.content #node的内容
    sous-nodes = node.xpathEval('*') #node下面的子node,同处理根目录的原理一下进行处理。
    ...

#释放内存
if doc:
    doc.freeDoc()

由于libxml2在读取xml文本后不会自动释放内存,因此会出现内存泄露问题,这个困扰了我好久,一直以为是Python的程序问题,,找了一大堆Python程序的内存管理资料,但是最后才发现是libxml2的问题。所以上面代码中给出了释放内存的指令,非常非常重要!

ps python下管理内存模块gc

import gc

a=['abc' for x in range(1000**5)]
del a
gc.collect()

TEI结构及的区别

众所周知,TEI定义了数据结构,数据类型甚至是数据属性,因此这里简单的介绍一下TEI文件的基本结构,及<TEI>和<teiCorpus>的区别。
这里TEI的版本为P5。

众所周知,TEI定义了数据结构,数据类型甚至是数据属性,因此这里简单的介绍一下TEI文件的基本结构,及<TEI>和<teiCorpus>的区别。
这里TEI的版本为P5。
Continue reading “TEI结构及的区别”

xslt结构,template/call-templates/apply-templates调用

template模板在XSLT中是一个很重要的工具,通过匹配的方法用来处理XML文档,在template一共有三个主要标签,,,这里就介绍一些这三个标签并且的用法。

template模板在XSLT中是一个很重要的工具,通过匹配的方法用来处理XML文档。
操作作顺序,阅读器逐行读取XML文件,若遇到某一个元素在XSLT中有相关模板,就根据模板的规则处理元素内的数据,例如
<xsl:template match=””>
    <xsl:value-of select=”.”/>
</xsl:template>
通过”/”,匹配XML的根元素,那么在阅读器读取到XML(等于开始读取XML文本)的根元素时,将通过这个模板的设置进行数据处理,这个命令是输出非标签文本。
例如只使用:
<xsl:template match=””>
</xsl:template>
由于里面没有使用任何的对匹配文本的处理方式,那么输出结果为空。
那么假如处理下面的XML:
<aa>
        <bb>
                bbb
        </bb>
        <cc>
                ccc
        </cc>
        <dd>
                ddd1
        </dd>
        <dd>
                ddd2
        </dd>
</aa>
XSLT只有一个模板
<xsl:template match=”cc”>
    <h1><xsl:value-of select=”.”/></1>
</xsl:template>
那么输出结果,只有ccc被标题化,其他的只是纯文本拷贝。
因此我们还可以使用另外一个template去处理剩下的标签。
需要注意的是,一当根元素给”/”匹配了之后,那么剩下来的的模板就不在匹配任何的元素了,这种情况下也就是通常XSLT写法。
XSLT文件其实是一个或者多个XML文件的样式表,里面包含的功能会很丰富,因此在整个XSLT文件中有许多的template模板,模板与模板之间通过以下两种方式来来穿插使用:
<xsl:apply-templates>
<xsl:call-template>
这两个功能都是调用其他的模板,但是有所区别:
<xsl:apply-templates>,是在匹配到某个元素的时候,才采用模板,因此一定需要在XML文件中存在这个元素,如果不存在,将不进行任何操作。
调用例子:
<xsl:template match=”/”>
     <xsl:apply-templates select=”cc”/>
</xsl:template>
<xsl:template match=”cc”>
    处理的内容
</xsl:template>
<xsl:call-tempalte>,是直接调用一个模板,并将需要处理的数据通过<xsl:with-param>形式传递给模板,就想编程语言中的函数一样。
调用例子:
<xsl:template match=”/”>
     <xsl:call-template name=”template-name”>
              <xsl:with-param name=”name1″ select=”cc”/>
              <xsl:with-param name=”name2″>
                   <xsl:value-of select=”cc”/>
              </xsl:with-param>
</xsl:template>
<xsl:template name=”template-name”>
    <xsl:param select=”name1″>
    <xsl:param select=”name2″>
     处理内容
</xsl:template>
<xsl:call-template name=”name1″>, 这里虽然选择了name1,但是这个name1并不是XML文中的元素,而是直接调用模板name1。
这里我们也简单的说一下两个<xsl:with-param>的区别:
前面一个直接带select的标签,它的功能是传递元素cc给模板,再通过模板来处理cc下面的其他数据
后面一个不带的标签,根据上面的定义,它只是传递cc的值给模板。
假如说,传递给模板的元素带有其他的标签,就像前一个传递的内容一样,可以通过xslt的功能处理
如<xsl:value-of select=”.”/>取cc元素及其子元素中的所有纯文本。
在这里我曾遇到一个问题,那么就是在传递”格式化的文本“给模板的时候,我只想添加其他的格式标签并要保留文本内的其他格式标签,这个时候需要用到的是<xsl:copy>和<xsl:copy-of>,具体的例子就不说啦,等下次写到<xsl:copy>和<xsl:copy-of>的时候再说啦。

64位Mod_wsgi支持win7,组建Apache的Python环境

Windows 7+Apache+Python+Mod_wsgi构建Python服务器,支持64位

Python网页服务器的搭建,Python网页架构主流配置由WSGI模块、Apache网页服务器、Django或Web.py框架构成(框架方面其实选择很多,个人比较喜欢DJANGO和Web.py)。

在这里,主要说明如何在Windows下构建Apache的Python平台,模块选择WSGI,框架使用Django。软件版本的选择:Windows7 + Python 2.7 + Apache 2.2.22 + Mod_wsgi 3.3。
python-django
Continue reading “64位Mod_wsgi支持win7,组建Apache的Python环境”