连接和重新排列文件的最有效方法

时间:2010-03-24 14:46:45

标签: python file concatenation

我正在从几个文件中读取,每个文件分为2个部分,首先是几千行的标题部分,后面是几千个主体。我的问题是我需要将这些文件连接到一个文件中,其中所有标题都在顶部,然后是正文。

目前我正在使用两个循环:一个用于拔出所有标头并写入它们,第二个用于写入每个文件的主体(我还包含一个tmp_count变量来限制行数在转储到文件之前加载到内存中。)

这很慢 - 13gb文件大约需要6分钟。任何人都可以告诉我如何优化这个或者如果有更快的方法在python中执行此操作?

谢谢!

这是我的代码:

def cat_files_sam(final_file_name,work_directory_master,file_count):

    final_file = open(final_file_name,"w")

    if len(file_count) > 1:
        file_count=sort_output_files(file_count)

    # only for @ headers    
    for bowtie_file in file_count:
        #print bowtie_file
        tmp_list = []

        tmp_count = 0
        for line in open(os.path.join(work_directory_master,bowtie_file)):
            if line.startswith("@"):

            if tmp_count == 1000000:
                final_file.writelines(tmp_list)
                tmp_list = []
                tmp_count = 0

            tmp_list.append(line)
            tmp_count += 1

        else:
            final_file.writelines(tmp_list)
            break

    for bowtie_file in file_count:
        #print bowtie_file
        tmp_list = []

        tmp_count = 0
        for line in open(os.path.join(work_directory_master,bowtie_file)):
            if line.startswith("@"):
            continue
        if tmp_count == 1000000:
            final_file.writelines(tmp_list)
            tmp_list = []
            tmp_count = 0

        tmp_list.append(line)
        tmp_count += 1
        final_file.writelines(tmp_list)

    final_file.close()

3 个答案:

答案 0 :(得分:2)

您希望移动13Gb数据的速度有多快?这个问题是I / O绑定的,而不是Python的问题。为了加快速度,请减少I / O.这意味着你要么(a)坚持你所拥有的速度,要么(b)应该重新调整工具链的后续元素以便就地处理文件,而不是需要一个巨大的13 Gb文件。

答案 1 :(得分:2)

您可以节省第二次跳过标题所需的时间,只要您有合理数量的备用磁盘空间:以及最终文件,也打开(对于'w +')临时文件{ {1}},然后执行:

temp_file

这应该可以提高程序的性能。微调现在硬编码的import shutil hdr_list = [] bod_list = [] dispatch = {True: (hdr_list, final_file), False: (bod_list, temp_file)} for bowtie_file in file_count: with open(os.path.join(work_directory_master,bowtie_file)) as f: for line in f: L, fou = dispatch[line[0]=='@'] L.append(f) if len(L) == 1000000: fou.writelines(L) del L[:] # write final parts, if any for L, fou in dispatch.items(): if L: fou.writelines(L) temp_file.seek(0) shutil.copyfileobj(temp_file, final_file) ,甚至完全取消列表并将每一行直接写入相应的文件(最终或临时),是您应该进行基准测试的其他选项(但如果您有无限制的话)记忆的数量,然后我希望它们无关紧要 - 但是,关于性能的直觉常常会产生误导,因此最好尝试和测量! - 。)。

答案 2 :(得分:0)

您要编写的代码中存在两个严重的低效率(这不是提供的代码):

  1. 您正在第一个主要for块中构建大量标题行列表,而不是仅仅将其写出来。
  2. 当您已经确定标题以(1)结尾的位置时,您将逐行跳过第二个主for块中的文件标题。请参阅file.seek and file.tell