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

发布于 2021-01-29 17:55:09

我正在python 2.7中读取800 GB的xml文件,并使用etree迭代解析器对其进行解析。

目前,我只使用open('foo.txt')没有缓冲参数。我是应该采用这种方法还是应该使用缓冲参数,还是应该使用io.BufferedReader或io.open或io.TextIOBase之类的方法,对此感到有些困惑。

朝正确方向的观点将不胜感激。

关注者
0
被浏览
50
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    默认情况下,标准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文件时,无论如何都会缓存磁盘缓存。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看