views:

61

answers:

3

I have some xml documents I need to run queries on. I've created some python scripts (using ElementTree) to do this, since I'm vaguely familiar with using it.

The way it works is I run the scripts several times with different arguments, depending on what I want to find out.

These files can be relatively large (10MB+) and so it takes rather a long time to parse them. On my system, just running:

tree = ElementTree.parse(document)

takes around 30 seconds, with a subsequent findall query only adding around a second to that.

Seeing as the way I'm doing this requires me to repeatedly parse the file, I was wondering if there was some sort of caching mechanism I can use so that the ElementTree.parse computation can be reduced on subsequent queries.

I realise the smart thing to do here may be to try and batch as many queries as possible together in the python script, but I was hoping there might be another way.

Thanks.

+1  A: 

First off, consider using the lxml implementation of ElementTree:
http://codespeak.net/lxml/
This is a wrapper for libxml2, which I find performs well.

Run python interactively, make multiple queries against the same etree object. ipython is an enhanced interactive python interpreter with easy access to introspection and convenience-syntax.

E.g. interactively examining note.xml with ipython using lxml.etree.

$ ipython
Python 2.5.1 (r251:54863, Jul 10 2008, 17:24:48)
Type "copyright", "credits" or "license" for more information.

IPython 0.8.2 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object'. ?object also works, ?? prints more.

In [1]: from lxml import etree

In [2]: doc = etree.parse(open("note.xml"))

In [3]: etree.dump(doc.getroot())
<note>
        <to>Tove</to>
        <from>Jani</from>
        <heading>Reminder</heading>
        <body>Don't forget me this weekend!</body>
</note>
In [4]: doc.xpath('/note/*')
Out[4]:
[<Element to at 89cf02c>,
 <Element from at 89cf054>,
 <Element heading at 89cf07c>,
 <Element body at 89cf0a4>]
MattH
A great suggestion, but not sure it will work for me as I actually want to run the python scripts from an applescript. I will see if I can make it work
Jack
+2  A: 

While I second the suggestion to use lxml, you can get a huge performance boost by using the builtin cElementTree.

from xml.etree import cElementTree as ElementTree
mikerobi
Yes I think that will work! The first time a query is run it takes around 15 seconds, but subsequent queries are around 1-2 seconds.As for using lxml my reason for not doing so is that I want to make sure these scripts will work out of the box on any mac I run them on, without needing to install anything else. I don't know if there's a way I could build lxml and just bundle it together with my .py files, if so please let me know how I do this
Jack
+1  A: 

Seconding the lxml recommendation, look at this article for how to improve performance by using an iterative (SAX-like) parsing method. It can be a pain at first since it can turn really procedural and messy, but it makes things faster. As you can see from these benchmarks, lxml is most likely your best bet for performance.

Tom
+1 Interesting article
MattH