Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';It’迭代多个文件的所有行的最具Python风格的方式是什么?_Python_File_Parsing_Logging - Fatal编程技术网

什么';It’迭代多个文件的所有行的最具Python风格的方式是什么?

什么';It’迭代多个文件的所有行的最具Python风格的方式是什么?,python,file,parsing,logging,Python,File,Parsing,Logging,我想把许多文件当作一个文件来处理。使用生成器获取[文件名]=>[文件对象]=>[行]或不将整个文件读入内存的正确Python方式是什么 我们都知道打开文件的正确方法: with open("auth.log", "rb") as f: print sum(f.readlines()) 我们知道将多个迭代器/生成器链接成一个长迭代器/生成器的正确方法: >>> list(itertools.chain(range(3), range(3))) [0, 1, 2, 0,

我想把许多文件当作一个文件来处理。使用生成器获取[文件名]=>[文件对象]=>[行]或不将整个文件读入内存的正确Python方式是什么

我们都知道打开文件的正确方法:

with open("auth.log", "rb") as f:
    print sum(f.readlines())
我们知道将多个迭代器/生成器链接成一个长迭代器/生成器的正确方法:

>>> list(itertools.chain(range(3), range(3)))
[0, 1, 2, 0, 1, 2]
但是如何将多个文件链接在一起并保留上下文管理器呢

with open("auth.log", "rb") as f0:
    with open("auth.log.1", "rb") as f1:
        for line in itertools.chain(f0, f1):
            do_stuff_with(line)

    # f1 is now closed
# f0 is now closed
# gross
我可以忽略上下文管理器,这样做,但感觉不对:

files = itertools.chain(*(open(f, "rb") for f in file_names))
for line in files:
    do_stuff_with(line)
或者这就是我要做的,我以后只需等待优雅的语法?

总是有

但是,阅读时,似乎无法将
fileinput.fileinput
用作上下文管理器1。要解决此问题,您可以使用,因为
FileInput
实例有一个合理实现的
close
方法:

from contextlib import closing
with closing(fileinput.input(filenames)) as line_iter:
    for line in line_iter:
        ...

使用上下文管理器的另一种方法是编写一个简单的函数,在文件上循环并生成行:

def fileinput(files):
    for f in files:
        with open(f,'r') as fin:
            for line in fin:
                yield line
没有真正需要的
itertools.chain
在这里我。。。这里的神奇之处在于
yield
语句,该语句用于将普通函数转换为极其懒惰的生成器


1另一方面,从python3.2开始,
fileinput.fileinput
作为上下文管理器实现,它与我们之前使用
contextlib
所做的完全相同。现在我们的例子是:

# Python 3.2+ version
with fileinput.input(filenames) as line_iter:
    for line in line_iter:
        ...

尽管另一个示例也适用于python3.2+。

还请注意,
files=itertools.chain(*(在文件名中f的open(f,“rb”)在这种情况下肯定不好。解包元组会导致在实际输入
构造函数之前打开所有文件。你最好使用
itertools.chain.from_iterable(文件名中fname的open(fname,'r'))
——事实上,这就是为什么首先需要存在
from iterable
classmethod的一个经典原因:)。@mgilson不知道
from iterable
是一件事!我很高兴我的用例是一个教科书上的例子,说明它为什么有用。我试图弄清楚如何在没有嵌套for循环的情况下正确地使用惰性计算。谢谢请注意,即使是iterable中的
也不能保证在完成迭代后所有文件都会关闭,因为您永远不知道
\uu del\uuu
何时会实际运行(尽管我很确定它们将在Cpython中)…有一种方法允许将多个上下文管理器视为一个(在您的案例中不需要,但在相关案例中可能有用).@Blender——这是一个不错的模块,没有被太多人使用,因为它的功能可以被
链所取代。from_iterable
itertools
collections
是人们90%的时间里使用的比较有名的工具。不过,我有点失望,它没有作为上下文管理器实现(它甚至不是一个新样式的类)。这似乎是一个非常简单的添加,但实际上,用contextlib包装起来很容易。从Python 3.2开始,
fileinput
可以用作上下文管理器(.@neddely--我很高兴他们在阅读源代码几分钟后就实现了它(在意识到这是一门老式课程之前)我不确定上下文管理器是否使用了旧式类…经过一个非常快速的测试后,它们似乎确实使用了…但是我认为关闭
contextlib.closing
仍然比一个子类好...@Conrad.Dean--这很合理。值得指出的是,
fileinput
使用了一个可选参数
openhook
将被调用,而不是
open
。因此您只需将文件的打开委托给
openhook
函数即可。
# Python 3.2+ version
with fileinput.input(filenames) as line_iter:
    for line in line_iter:
        ...