python中大文件的高效文件缓冲和扫描方法

ebl*_*ume 9 python io performance bioinformatics fasta

我遇到的问题描述有点复杂,我会提供更完整的信息.对于不耐烦的人,这是我可以总结的最简单的方法:

抛出换行符时,将文本文件拆分为大小为N(绑定N,例如36)的所有(重叠)子串的最快(最短执行时间)方式是什么.

我正在编写一个模块,用于解析基于FASTA ascii的基因组格式的文件.这些文件包含所谓的'hg18'人类参考基因组,如果您愿意,可以从UCSC基因组浏览器(go slugs!)下载.

正如您将注意到的,基因组文件由chr [1..22] .fa和chr [XY] .fa组成,以及一组未在此模块中使用的其他小文件.

已经存在几个用于解析FASTA文件的模块,例如BioPython的SeqIO.(对不起,我发布了一个链接,但我还没有这么做.)不幸的是,我能找到的每个模块都没有做我想做的具体操作.

我的模块需要将基因组数据(例如,'CAGTACGTCAGACTATACGGAGCTA'可以是一条线)分成每个重叠的N长度子串.让我举一个例子,使用一个非常小的文件(实际的染色体文件长度在355到2000万个字符之间),N = 8

>>>import cStringIO
>>>example_file = cStringIO.StringIO("""\
>header
CAGTcag
TFgcACF
""")
>>>for read in parse(example_file):
...    print read
...
CAGTCAGTF
AGTCAGTFG
GTCAGTFGC
TCAGTFGCA
CAGTFGCAC
AGTFGCACF

我发现的功能从我能想到的方法中获得了绝对最佳的性能:


def parse(file):
  size = 8 # of course in my code this is a function argument
  file.readline() # skip past the header
  buffer = ''
  for line in file:
    buffer += line.rstrip().upper()
    while len(buffer) >= size:
      yield buffer[:size]
      buffer = buffer[1:]
Run Code Online (Sandbox Code Playgroud)

这很有效,但不幸的是,用这种方式解析人类基因组还需要大约1.5小时(见下面的注释).也许这是我将要看到的最好的方法(一个完整的代码重构可能是有序的,但我想避免它,因为这种方法在代码的其他方面有一些非常具体的优势),但我以为我会把它转交给社区.

谢谢!

  • 注意,这次包括许多额外的计算,例如计算反向链读取和在大小约为5G的散列上进行散列表查找.

回答结论:事实证明,使用fileobj.read()然后操作结果字符串(string.replace()等)与程序的其余部分相比花费的时间和内存相对较少,所以我使用了做法.感谢大家!

die*_*dha 3

一些经典的 IO 绑定更改。

  • 使用较低级别的读取操作,例如os.read读入大型固定缓冲区。
  • 使用线程/多处理,其中一个进行读取和缓冲,另一个进行处理。
  • 如果您有多个处理器/机器,请使用 multiprocessing/mq 在 CPU 之间分配处理(ala map-reduce)。

使用较低级别的读取操作不会造成太大的重写。其他的将是相当大的重写。