在Python 2.7中高效读取800 GB XML文件

时间:2013-02-13 21:11:28

标签: python xml python-2.7 file io

我正在python 2.7中读取一个800 GB的xml文件,并使用etree迭代解析器解析它。

目前,我只使用open('foo.txt')而没有缓冲参数。我有点困惑这是否是我应该采取的方法,或者我应该使用缓冲参数或使用io中的东西,如io.BufferedReader或io.open或io.TextIOBase。

非常感谢正确方向上的一点。

3 个答案:

答案 0 :(得分:15)

默认情况下,标准open() function已经返回一个缓冲文件(如果在您的平台上可用)。对于通常完全缓冲的文件对象。

通常这里意味着Python将此保留给C stdlib实现;它使用fopen() call(Windows上的wfopen()来支持UTF-16文件名),这意味着选择了文件的默认缓冲;在Linux上我相信这将是8kb。对于像XML解析这样的纯读取操作,这种类型的缓冲完全你想要的。

iterparse完成的XML解析以16384字节(16kb)的块读取文件。

如果要控制buffersize,请使用buffering关键字参数:

open('foo.xml', buffering=(2<<16) + 8)  # buffer enough for 8 full parser reads

将覆盖默认缓冲区大小(我希望与文件块大小或其倍数相匹配)。根据{{​​3}}增加读缓冲区应该帮助,并且使用至少4倍的预期读取块大小加上8个字节的大小将提高读取性能。在上面的例子中,我将它设置为ElementTree读取大小的8倍。

this article表示对象的新Python 3 I / O结构,其中I / O已拆分为新的类类型层次结构,以提供更大的灵活性。价格更加间接,数据必须通过更多层,而Python C代码本身更有效,而不是将其留给操作系统。

可以尝试查看io.open('foo.xml', 'rb', buffering=2<<16)是否会更好地执行。以rb模式打开将为您提供io.open() function

想要使用io.TextIOWrapper;底层的expat解析器需要原始数据,因为它将解码您的XML文件编码本身。它只会增加额外的开销;如果您在r(文本模式)中打开,则会获得此类型。

使用io.open()可以为您提供更多灵活性和更丰富的API,但使用open()而不是fopen()打开底层C文件对象,并且所有缓冲都由Python处理{ {1}}实施。

我认为你的问题将是处理这个野兽,而不是文件读取。在读取800GB文件时,磁盘缓存无论如何都会被拍摄。

答案 1 :(得分:1)

您是否尝试过懒惰功能?:Lazy Method for Reading Big File in Python?

这似乎已经回答了你的问题。但是,我会考虑使用这种方法将数据写入DATABASE,mysql是免费的:http://dev.mysql.com/downloads/,NoSQL也是免费的,可能更适合编写800gb数据或类似数量的操作:{ {3}}

答案 2 :(得分:1)

我没有尝试使用这些史诗般的xml文件,但上次我不得不处理大型(相对简单的)xml文件时,我使用了sax parser

它基本上为每个“事件”提供回调,并留给您存储所需的数据。您可以提供一个打开的文件,这样您就不必一次性阅读它。