首页 > 解决方案 > 保持文件句柄打开的缺点?

问题描述

我正在解析一些 XML 并将数据写入不同的文件,具体取决于当前正在处理的 XML 元素。处理一个元素真的很快,写入数据也是。因此,文件需要经常打开和关闭。例如,给定一个巨大的file

for _, node in lxml.etree.iterparse(file):
    with open(f"{node.tag}.txt", 'a') as fout:
        fout.write(node.attrib['someattr']+'\n'])

这会起作用,但相对而言,打开和关闭文件会花费很多时间。(注意:这是一个玩具程序。实际上我写入文件的实际内容以及文件名是不同的。有关数据详细信息,请参阅最后一段。)

一种替代方法可能是:

fhs = {}
for _, node in lxml.etree.iterparse(file):
    if node.tag not in fhs:
        fhs[node.tag] = open(f"{node.tag}.txt", 'w')

    fhs[node.tag].write(node.attrib['someattr']+'\n'])

for _, fh in fhs.items(): fh.close()

这将使文件保持打开状态,直到 XML 解析完成。有一些查找开销,但与迭代打开和关闭文件相比,这应该是最小的。

我的问题是,这种方法的缺点是什么,性能方面?我知道这会使其他进程无法访问打开的文件,并且您可能会遇到打开文件的限制。但是,我对性能问题更感兴趣。保持所有文件句柄打开是否会产生某种内存问题或处理问题?在这种情况下可能会发生过多的文件缓冲?我不确定,所以这个问题。

输入的 XML 文件最大可达 70GB 左右。生成的文件数量限制在 35 个左右,这与我在上述帖子中读到的限制相去甚远。

标签: pythonpython-3.xperformancefile-handling

解决方案


您已经提到的明显缺点是,将需要大量内存来保持所有文件句柄处于打开状态,这当然取决于文件的数量。这是您必须自己进行的计算。并且不要忘记写锁。

否则的话,它并没有太大的问题,但如果采取一些预防措施会很好:

fhs = {}
try:
    for _, node in lxml.etree.iterparse(file):
        if node.tag not in fhs:
            fhs[node.tag] = open(f"{node.tag}.txt", 'w')

        fhs[node.tag].write(node.attrib['someattr']+'\n'])
finally:
    for fh in fhs.values(): fh.close()

注意:在 python 中循环一个 dict 时,你得到的项目实际上只是键。我建议做for key, item in d.items():for item in d.values():


推荐阅读