当前位置: 首页 > 知识库问答 >
问题:

在Python中生成超大型文本文件的时间性能

於彬
2023-03-14

我需要生成一个非常大的文本文件。每一行都有一个简单的格式:

Seq_num<SPACE>num_val
12343234 759

假设我要生成一个有1亿行的文件。我尝试了两种方法,令人惊讶的是,它们给出了非常不同的时间表现。

>

  • 用于100m以上的循环。在每个循环中,我生成seq_num num_val 的短字符串,然后将其写入文件。这种方法需要很多时间。

    ## APPROACH 1  
    for seq_id in seq_ids:
        num_val=rand()
        line=seq_id+' '+num_val
        data_file.write(line)
    
    ## APPROACH 2  
    data_lines=list()
    for seq_id in seq_ids:
        num_val=rand()
        l=seq_id+' '+num_val
        data_lines.append(l)
    for line in data_lines:
        data_file.write(line)
    

    请注意:

    • 方法2有2个循环,而不是1个循环。
    • 对于方法1和方法2,我都在循环中写入文件。因此这两个步骤必须相同。

    因此方法1必须花费更少的时间。有什么提示我错过了什么吗?

  • 共有1个答案

    常雅达
    2023-03-14

    考虑到方法2,我想我可以假设在需要将数据写入文件之前,您已经拥有了所有行的数据(或者至少是大块的)。

    其他的答案都很好,阅读它们真的很有启发,但它们都集中在优化文件编写或避免用列表理解替换第一个for循环(众所周知,这会更快)。

    他们忽略了这样一个事实,即您在for循环中迭代来写入文件,而这并不是真正必要的。

    不是这样做,而是通过增加内存的使用(在这种情况下是可以负担得起的,因为一个1亿行的文件大约需要600 MB),您可以使用python str的格式化或连接特性,以更高效的方式创建一个字符串,然后将大字符串写入文件。也依赖于列表理解来获取要格式化的数据。

    使用@Tombart答案的loop1和loop2,我分别得到经过时间0:00:01.028567经过时间0:00:01.017042

    使用此代码时:

    start = datetime.now()
    
    data_file = open('file.txt', 'w')
    data_lines = ( '%i %f\n'%(seq_id, random.random()) 
                                for seq_id in xrange(0, 1000000) )
    contents = ''.join(data_lines)
    data_file.write(contents) 
    
    end = datetime.now()
    print("elapsed time %s" % (end - start))
    

    我得到运行时间0:00:00.722788,这大约快了25%。

    注意,data_lines是一个生成器表达式,因此列表并没有真正存储在内存中,而是由join方法按需生成和使用行。这意味着唯一显著占用内存的变量contents。这也略微减少了运行时间。

    如果文本是很大的,以完成所有的工作在内存中,你可以总是分开的块。即格式化字符串并每隔一百万行左右写入文件。

    结论:

    • 总是尝试进行列表理解,而不是简单的for循环(列表理解甚至比filter更快,用于筛选列表,请参阅此处)。
    • 如果内存或实现限制允许,请尝试使用格式联接函数同时创建和编码字符串内容。
    • 如果可能且代码仍可读,请使用内置函数以避免for循环。例如,使用列表的extend函数而不是迭代和使用append。事实上,前面的两点都可以看作是这句话的例子。

    备注。虽然这个答案本身可以被认为是有用的,但它并没有完全解决问题,这就是为什么问题中的two loops选项在某些环境中似乎运行得更快。对于这一点,也许@Aiken Drum下面的回答可以为这件事带来一些启示。

     类似资料:
    • 我正在写一个小程序,可以处理大的(最多无限个)文本文件。处理过程将相当简单(将部分内容修剪并处理成单独的字符串,然后打印出来)。然而,由于数据的长度可能是无限的,我可能会遇到超过堆的问题。我想到的第一个解决方案是使用流来处理数据。然而,Files类中的lines()方法只能将文本分成行。我的线条也可以无限长! 我遇到的另一个解决方案是使用scanner useDelimiter方法: 这种方法会阻

    • 由于多值字段和维度使用报价,csv读取器读取此文件失败。我的函数(上面代码中的函数f)如果那个逗号在属于同一字段的两个数据之间,就用分号代替逗号,如果那个引号是维度的东西,就用'inch'代替。

    • 我正试图读/写一个巨大的文本文件。但当我尝试这样做时,我得到了错误: 我的代码如下: 我尝试添加一个计数器(count),这样它可以在读取一定数量的行后刷新缓冲区。它不起作用。我知道计数器工作不正常。在执行“while”循环的特殊次数后,它不会变为零。我在while循环之前和之后添加了一个“for”循环来清空计数器,但效果不太好。 有什么建议吗?

    • 我使用以下两段代码来读取一个大文件。 这使用: 对我错过的东西的想法?即使使用了'read()'方法,BufferedReader也应该比从FileReader读取更好的性能吗?

    • 本文向大家介绍python处理文本文件并生成指定格式的文件,包括了python处理文本文件并生成指定格式的文件的使用技巧和注意事项,需要的朋友参考一下

    • 问题内容: 在Linux中,有一个文件,顾名思义就是管道。因此,假设我想使用Python从中读取前50个字节,然后运行以下代码: 我们可以看到打开文件的速度很快(如果拥有超级用户权限)-但是,如果那时文件为空,它将简单地阻塞(即使有内容,内容也将被转储,直到没有内容为止)。更多内容,然后该文件将再次阻止)。然后我必须按- 用… 中断Python脚本。 如何让Python 2.7读取超时? 也就是说