Python 如何使用“打开多个文件(事先未知的文件数)”;用开放的;陈述

Python 如何使用“打开多个文件(事先未知的文件数)”;用开放的;陈述,python,file,python-2.7,merge,with-statement,Python,File,Python 2.7,Merge,With Statement,我特别需要使用with open语句来打开文件,因为我需要一起打开几百个文件,并使用K-way merge将它们合并。我明白,理想情况下我应该保持低K,但我没有预见到这个问题 从零开始现在不是一个选择,因为我有一个最后期限。因此,在这一点上,我需要非常快速的I/O,它不会将文件的整个/巨大部分存储在内存中(因为有数百个文件,每个文件大约10MB)。我只需要一次读一行就可以了。减少内存使用是我现在的主要关注点 我了解到使用open打开是最有效的技术,但我不知道如何使用open语句将所有文件一起打开

我特别需要使用
with open
语句来打开文件,因为我需要一起打开几百个文件,并使用K-way merge将它们合并。我明白,理想情况下我应该保持低K,但我没有预见到这个问题

从零开始现在不是一个选择,因为我有一个最后期限。因此,在这一点上,我需要非常快速的I/O,它不会将文件的整个/巨大部分存储在内存中(因为有数百个文件,每个文件大约10MB)。我只需要一次读一行就可以了。减少内存使用是我现在的主要关注点

我了解到使用open打开
是最有效的技术,但我不知道如何使用open
语句将所有文件一起打开。原谅我的初学者无知

更新:此问题已解决。事实证明,问题根本不是我是如何打开文件的。我发现过多的内存使用是由于垃圾收集效率低下造成的。我根本没有对open使用
。我使用了常规的
f=open()
f.close()
。垃圾收集拯救了这一天

with open(...) as f: 
    # do stuff 
大致翻译为

f = open(...)
# do stuff
f.close()
在您的情况下,我不会将
与open
语法一起使用。如果您有一个文件名列表,那么执行以下操作

filenames = os.listdir(file_directory)
open_files = map(open, filenames)
# do stuff
for f in open_files:
    f.close()
如果您真的想将
与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
在这种情况下,我看到的使用上下文管理器的唯一优点是您不会忘记关闭文件。但是手动关闭文件并没有什么错。请记住,当您的程序退出时,操作系统将回收其资源

大致翻译为

f = open(...)
# do stuff
f.close()
在您的情况下,我不会将
与open
语法一起使用。如果您有一个文件名列表,那么执行以下操作

filenames = os.listdir(file_directory)
open_files = map(open, filenames)
# do stuff
for f in open_files:
    f.close()
如果您真的想将
与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

在这种情况下,我看到的使用上下文管理器的唯一优点是您不会忘记关闭文件。但是手动关闭文件并没有什么错。请记住,当您的程序退出时,操作系统将回收其资源。

编写您自己的上下文管理器来处理这一问题相当容易,方法是使用内置函数装饰器定义“使用
语句上下文管理器的工厂函数”,如文档所述。例如:

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()
        ...

编写自己的上下文管理器来处理这一问题相当容易,方法是使用内置函数装饰器定义“使用语句上下文管理器的
工厂函数”。例如:

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()
        ...

虽然不是2.7版的解决方案,但我应该注意到,3.3+版有一个好的、正确的解决方案,可以用来正确地实现这一点(当您自己运行时,很难正确地实现这一点),而且非常好:

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
s失败,则在该点之前成功的所有
open
s将被决定性地清除;在这种情况下,大多数简单的解决方案最终都无法清理,充其量只能依靠垃圾收集器,而在锁获取这样的情况下,如果没有要收集的对象,则无法释放锁


由于此问题被标记为未指定Python版本的a的“原始”问题,因此在此发布。

虽然不是2.7的解决方案,但我应该指出,3.3+有一个好的、正确的解决方案,可用于正确地执行此操作(当您自己运行时,很难正确地执行),并且很好地:

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
s失败,则在该点之前成功的所有
open
s将被决定性地清除;在这种情况下,大多数简单的解决方案最终都无法清理,充其量只能依靠垃圾收集器,而在锁获取这样的情况下,如果没有要收集的对象,则无法释放锁


由于此问题被标记为未指定Python版本的问题的“原始”问题,因此在此发布。

我认为使用open的
f=open()更有效。

。。。关闭(f)
。它应该更方便,但在你的情况下,听起来好像不是这样。您只需打开一堆文件并将文件对象保存在列表中。
with
语句与效率无关,它只确保隐式关闭文件(即使发生异常)。正如@MarkkuK所说,您可以将对文件对象的引用存储在一个列表中,然后在最后手动关闭它们,并使用try finally块确保即使发生错误,文件也会关闭。感谢您的快速响应。你能推荐一个即使我一起打开几百个文件,内存使用率也不会这么高的替代方案吗?因为我一次只需要从这些文件中读取一行,所以我认为如果我使用一些技术,不在缓冲区中加载大部分文件,这会有所帮助。。。etc或要从每个文件中读取第一行,然后从每个文件中读取第二行…?使用文件对象的
读取行
-方法读取一行。重复使用将每次检索下一行:
f=open(file);f、 readline();f、 readline()。。。;f、 close()
我不认为使用open的
f=open()更有效。。。关闭(f)
。它应该更方便,但在你的情况下,听起来好像不是这样。您只需打开一堆文件,并将文件对象保存在列表中。
with
语句与效率无关,仅