对于2Gb文本文件,搁架字典大小> 100Gb

时间:2014-11-23 12:33:58

标签: python out-of-memory bioinformatics shelve

我正在从基因组FASTA文件中创建序列的搁置文件:

# Import necessary libraries
import shelve
from Bio import SeqIO

# Create dictionary of genomic sequences
genome = {}
with open("Mus_musculus.GRCm38.dna.primary_assembly.fa") as handle:
    for record in SeqIO.parse(handle, "fasta"):
        genome[str(record.id)] = str(record.seq)

# Shelve genome sequences
myShelve = shelve.open("Mus_musculus.GRCm38.dna.primary_assembly.db")
myShelve.update(genome)
myShelve.close()

文件本身是2.6Gb,但是当我试图搁置它时,正在生成一个> 100Gb的文件,而且我的计算机会抛出一些关于内存不足和启动磁盘已满的投诉。这似乎只发生在我尝试在OSX Yosemite下运行时,在Ubuntu上它按预期工作。有什么建议为什么这不起作用?我正在使用Python 3.4.2

2 个答案:

答案 0 :(得分:2)

通过import dbm; print(dbm.whichdb('your_file.db')验证dbm使用的接口.shelve使用的文件格式取决于系统及其接口上可用的最佳二进制包。最新版本为gdbm,而dumb是后备解决方案,如果未找到二进制文件,则ndbm介于两者之间。 https://docs.python.org/3/library/shelve.html
https://docs.python.org/3/library/dbm.html

如果丢失文件系统缓存的所有内存,则在内存中包含所有数据是不利的。更小的块更新更好。如果项目一个接一个地更新,我甚至看不到减速。

myShelve = shelve.open("Mus_musculus.GRCm38.dna.primary_assembly.db")
with open("Mus_musculus.GRCm38.dna.primary_assembly.fa") as handle:
    for i, record in enumerate(SeqIO.parse(handle, "fasta")):
        myShelve.update([(str(record.id), str(record.seq))])
myShelve.close()

众所周知,如果应用程序在更新后崩溃而不调用数据库close,则dbm数据库会碎片化。我认为这是你的情况。现在您可能还没有大文件中的重要数据,但将来您可以按gdbm.reorganize()对数据库进行碎片整理。

答案 1 :(得分:0)

我遇到了同样的问题:在一个带有大约4兆字节数据的架子的macOS系统上,磁盘上的巨大容量增加到了29千兆字节!这显然是因为我一遍又一遍地更新了货架上的相同键值对。

由于我的搁架基于GNU dbm,我能够使用他关于重组的提示。这是在几秒钟内将搁置文件恢复到正常大小的代码:

import dbm
db = dbm.open(shelfFileName, 'w')
db.reorganize()
db.close()

我不确定这种技术是否适用于其他(非GNU)dbms。要测试dbm系统,请记住@hynekcer显示的代码:

import dbm
print( dbm.whichdb(shelfFileName) )

如果您的系统使用GNU dbm,则应输出'dbm.gnu'(这是旧gdbm的新名称)。