如何在python中同时读取和处理多个文件

如何在python中同时读取和处理多个文件,python,Python,我有多个文件,我想同时读取它们,从每一行提取一个数字,然后进行平均。对于少量文件,我在itertools模块中使用izip实现了这一点。这是我的密码 from itertools import izip import math g=open("MSDpara_ave_nvt.dat",'w') with open("sample1/err_msdCECfortran_nvt.dat",'r') as f1, \ open("sample2/err_msdCECfortran_nvt

我有多个文件,我想同时读取它们,从每一行提取一个数字,然后进行平均。对于少量文件,我在itertools模块中使用izip实现了这一点。这是我的密码

from itertools import izip
import math

g=open("MSDpara_ave_nvt.dat",'w')

with open("sample1/err_msdCECfortran_nvt.dat",'r') as f1, \
     open("sample2/err_msdCECfortran_nvt.dat",'r') as f2, \
     open("sample3/err_msdCECfortran_nvt.dat",'r') as f3, \
     open("err_msdCECfortran_nvt.dat",'r') as f4:

     for x,y,z,bg in izip(f1,f2,f3,f4):
         args1=x.split()
         i1 = float(args1[0])
         msd1 = float(args1[1])


         args2=y.split()
         i2 = float(args2[0])
         msd2 = float(args2[1])


         args3=z.split()
         i3 = float(args3[0])
         msd3 = float(args3[1])

         args4=bg.split()
         i4 = float(args4[0])
         msd4 = float(args4[1])


         msdave = (msd1 + msd2 + msd3 + msd4)/4.0

         print>>g, "%e  %e" %(i1, msdave)

 f1.close()
 f2.close()
 f3.close()
 f4.close()
 g.close()
这个代码工作正常。但是如果我想同时处理100个文件,如果我这样做,代码就会变得非常冗长。还有其他更简单的方法吗?看起来fileinput模块也可以处理多个文件,但我不知道它是否可以同时处理


谢谢。

带有open模式的
很好,但在这种情况下,它会妨碍您。您可以打开文件列表,然后在
izip
中使用该列表:

filenames = ["sample1/err_msdCECfortran_nvt.dat",...]
files = [open(i, "r") for i in filenames]
for rows in izip(*files):
    # rows is now a tuple containing one row from each file

在Python3.3+中,您还可以在
with
块中使用:

filenames = ["sample1/err_msdCECfortran_nvt.dat",...]
with ExitStack() as stack:
    files = [stack.enter_context(open(i, "r")) for i in filenames]
    for rows in zip(*files):
        # rows is now a tuple containing one row from each file

在Python<3.3中,要将
结合使用,并发挥其所有优势(例如,无论您如何退出块,都能及时关闭),您需要创建自己的上下文管理器:

class FileListReader(object):

    def init(self, filenames):
        self.files = [open(i, "r") for i in filenames]

    def __enter__(self):
        for i in files:
            i.__enter__()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        for i in files:
            i.__exit__(exc_type, exc_value, traceback)
然后你可以做:

filenames = ["sample1/err_msdCECfortran_nvt.dat",...]
with FileListReader(filenames) as f:
    for rows in izip(*f.files):
        #...

不过,在这种情况下,最后一个可能会被认为过于工程化。

您不需要显式关闭在
with
语句中打开的文件。OP可以升级到现代Python并使用@DSM,感谢您的链接,而不是创建新的文件。我不知道这个(我使用2.7)。如果只使用一次,那么代码肯定会更少。我将把它整合到答案中。非常感谢,@otus。这很有帮助。所以,如果我对izip(files)中的行执行'files=[open(I,“r”)for I in filenames]:'如您所说,我如何从每个元组“rows”中读取行?显然我不能使用readline()。@otus,似乎元组“rows”不是字符串的元组。如果我打印元组“rows”的内容,我只得到类似“”的内容。如果我用“len(rows)”进一步观察元组“rows”的维度,就会发现“rows”的维度是一个。我有点困惑,为什么这个元组“rows”在我的数据文件中没有像你提到的那样包含一行字符串。@user2226358,对不起,我忘记了
中的星号*
。答案已更新。(它将列表作为多个参数而不是一个参数传递,因此
zip
将确实压缩它们。)