我有一个20个文件名的列表,比如['file1.txt', 'file2.txt',…]。我想写一个Python脚本将这些文件连接到一个新文件中。我可以通过f = open(…)打开每个文件,通过调用f.r edline()逐行读取,并将每行写入新文件。这对我来说似乎不是很“优雅”,尤其是我必须一行一行地读/写的部分。

在Python中是否有更“优雅”的方式来做到这一点?


当前回答

使用shutil.copyfileobj。

它会自动读取输入文件的块为您,这是更有效的读取输入文件,即使一些输入文件太大,无法装入内存也能工作:

import shutil

with open('output_file.txt','wb') as wfd:
    for f in ['seg1.txt','seg2.txt','seg3.txt']:
        with open(f,'rb') as fd:
            shutil.copyfileobj(fd, wfd)

其他回答

@inspectorG4dget答案的替代答案(到2016年3月29日为止的最佳答案)。我测试了3个436MB的文件。

@inspectorG4dget答案:162秒

解决方案:125秒

from subprocess import Popen
filenames = ['file1.txt', 'file2.txt', 'file3.txt']
fbatch = open('batch.bat','w')
str ="type "
for f in filenames:
    str+= f + " "
fbatch.write(str + " > file4results.txt")
fbatch.close()
p = Popen("batch.bat", cwd=r"Drive:\Path\to\folder")
stdout, stderr = p.communicate()

其思想是创建一个批处理文件并执行它,利用“旧的好技术”。它是半python,但运行速度更快。适用于windows。

def concatFiles():
    path = 'input/'
    files = os.listdir(path)
    for idx, infile in enumerate(files):
        print ("File #" + str(idx) + "  " + infile)
    concat = ''.join([open(path + f).read() for f in files])
    with open("output_concatFile.txt", "w") as fo:
        fo.write(path + concat)

if __name__ == "__main__":
    concatFiles()
  import os
  files=os.listdir()
  print(files)
  print('#',tuple(files))
  name=input('Enter the inclusive file name: ')
  exten=input('Enter the type(extension): ')
  filename=name+'.'+exten
  output_file=open(filename,'w+')
  for i in files:
    print(i)
    j=files.index(i)
    f_j=open(i,'r')
    print(f_j.read())
    for x in f_j:
      outfile.write(x)

这正是fileinput的作用:

import fileinput
with open(outfilename, 'w') as fout, fileinput.input(filenames) as fin:
    for line in fin:
        fout.write(line)

对于这个用例,它实际上并不比手动遍历文件简单多少,但在其他情况下,使用单个迭代器遍历所有文件,就像它们是单个文件一样非常方便。(此外,fileinput在完成后立即关闭每个文件的事实意味着不需要使用或关闭每个文件,但这只是节省一行,不是什么大不了的事情。)

在fileinput中还有一些其他漂亮的特性,比如通过过滤每一行来对文件进行就地修改的能力。


正如评论中所指出的,并在另一篇文章中讨论,Python 2.7的文件输入将无法正常工作。这里略有修改,使代码符合Python 2.7

with open('outfilename', 'w') as fout:
    fin = fileinput.input(filenames)
    for line in fin:
        fout.write(line)
    fin.close()

我不知道什么叫优雅,但这招管用:

    import glob
    import os
    for f in glob.glob("file*.txt"):
         os.system("cat "+f+" >> OutFile.txt")