在Python 2.7中高效读取800 GB XML文件
我正在python 2.7中读取800 GB的xml文件,并使用etree迭代解析器对其进行解析。
目前,我只使用open('foo.txt')
没有缓冲参数。我是应该采用这种方法还是应该使用缓冲参数,还是应该使用io.BufferedReader或io.open或io.TextIOBase之类的方法,对此感到有些困惑。
朝正确方向的观点将不胜感激。
-
默认情况下,标准
open()
函数已经返回一个缓冲文件(如果在您的平台上可用)。对于
通常 完全缓冲的文件对象。通常, 这里意味着Python将其留给C
stdlib实现;它使用fopen()
调用(wfopen()
在Windows上支持UTF-16文件名),这意味着已选择文件的默认缓冲;在Linux上,我相信是8kb。对于像XML解析这样的纯读取操作,这种类型的缓冲
正是 您想要的。通过XML解析完成
iterparse
的文件以16384字节(16kb)的块读取。如果要控制缓冲区大小,请使用
buffering
关键字参数:open('foo.xml', buffering=(2<<16) + 8) # buffer enough for 8 full parser reads
它将覆盖默认的缓冲区大小(我希望与文件块大小或其倍数匹配)。根据这篇文章,增加读取缓冲区
应该会 有所帮助,并且使用至少预期读取块大小的4倍加上8个字节的大小将提高读取性能。在上面的示例中,我将其设置为ElementTree读取大小的8倍。该
io.open()
函数表示对象的新Python
3 I / O结构,其中I / O被拆分为新的类类型层次结构,从而为您提供了更大的灵活性。价格更加间接,要传递的数据层更多,并且Python
C代码本身会执行更多工作,而不是将这些工作留给操作系统。您 可以 尝试看看效果是否
io.open('foo.xml', 'rb', buffering=2<<16)
会更好。在rb
模式下打开将为您提供io.BufferedReader
实例。你 不 希望使用
io.TextIOWrapper
;
底层的expat解析器需要原始数据,因为它将解码XML文件本身的编码。这只会增加额外的开销;如果r
改为以(文本模式)打开,则会得到此类型。使用
io.open()
可能会为您提供更大的灵活性和更丰富的API,但是使用open()
而不是可以打开基础C文件对象fopen()
,并且所有缓冲都由Pythonio.BufferedIOBase
实现处理。我认为您的问题将是处理这头野兽,而不是读取文件。读取800GB文件时,无论如何都会缓存磁盘缓存。