[英]How can I open multiple files (number of files unknown beforehand) using “with open” statement?
我特别需要使用with open
语句来打开文件,因为我需要一起打开几百个文件并使用K-way merge进行合并。 我了解,理想情况下我应该保持K低,但我没有预见到这个问题。
由于我有一个截止日期,因此现在不能从头开始。 因此,在这一点上,我需要非常快速的I / O,它不能将文件的整个/巨大部分存储在内存中(因为有数百个文件,每个文件约10MB)。 我只需要一次阅读一行即可进行K向合并。 减少内存使用是我目前的主要重点。
我了解到, with open
是最有效的方法,但我不知道如何open
所有文件一起在一个with open
的语句。 对不起,我的初学者无知!
更新:此问题已解决。 事实证明,问题根本不在于我如何打开文件。 我发现过多的内存使用是由于低效率的垃圾回收所致。 我根本不使用with open
。 我使用了常规的f=open()
和f.close()
。 垃圾收集挽救了这一天。
通过使用内置的contextmanger
函数装饰器来定义文档说明中的“ with
语句上下文管理器的工厂函数”,从而编写自己的上下文管理器来处理此问题非常容易。 例如:
from contextlib import contextmanager
@contextmanager
def multi_file_manager(files, mode='rt'):
""" Open multiple files and make sure they all get closed. """
files = [open(file, mode) for file in files]
yield files
for file in files:
file.close()
filenames = 'file1', 'file2', 'file3'
with multi_file_manager(filenames) as files:
a = files[0].readline()
b = files[2].readline()
...
with open(...) as f:
# do stuff
大致翻译成
f = open(...)
# do stuff
f.close()
在您的情况下,我不会将with open
语法with open
使用。 如果您有文件名列表,请执行以下操作
filenames = os.listdir(file_directory)
open_files = map(open, filenames)
# do stuff
for f in open_files:
f.close()
如果您确实想使用with open
语法,则可以创建自己的上下文管理器来接受文件名列表
class MultipleFileManager(object):
def __init__(self, files):
self.files = files
def __enter__(self):
self.open_files = map(open, self.files)
return self.open_files
def __exit__(self):
for f in self.open_files:
f.close()
然后像这样使用它:
filenames = os.listdir(file_directory)
with MulitpleFileManager(filenames) as files:
for f in files:
# do stuff
在这种情况下,使用上下文管理器的唯一好处是您不会忘记关闭文件。 但是手动关闭文件没有任何问题。 记住,当您的程序退出时,操作系统将回收其资源。
虽然不是2.7的解决方案,我应该注意到有一个良好的,为3.3+正确的解决方案, contextlib.ExitStack
,它可以用来正确做到这一点(令人惊讶的困难,当你滚你自己得到的权利),并很好地:
from contextlib import ExitStack
with open('source_dataset.txt') as src_file, ExitStack() as stack:
files = [stack.enter_context(open(fname, 'w')) for fname in fname_list]
... do stuff with src_file and the values in files ...
... src_file and all elements in stack cleaned up on block exit ...
重要的是,如果任何一个open
失败,则将确定性地清除在该点之前成功的所有open
。 在这种情况下,大多数幼稚的解决方案最终都无法清理,只能依靠垃圾回收器,并且在诸如锁获取而没有对象可以收集的情况下,也无法释放锁。
由于此问题被标记为“原始”,表示未指定Python版本的重复项 ,因此在此处发布。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.