我正在python 2.7中读取一个800 GB的xml文件,并使用etree迭代解析器解析它。
目前,我只使用open('foo.txt')
而没有缓冲参数。我有点困惑这是否是我应该采取的方法,或者我应该使用缓冲参数或使用io中的东西,如io.BufferedReader或io.open或io.TextIOBase。
非常感谢正确方向上的一点。
答案 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。
它基本上为每个“事件”提供回调,并留给您存储所需的数据。您可以提供一个打开的文件,这样您就不必一次性阅读它。