0

私はPythonを初めて使用するので、この例が些細なことでしたら申し訳ありません。

2 つの大きなデータファイル (それぞれ約 40 GB) の一部を、わずかに変更された形式の 1 つの結果ファイルに抽出して抽出する簡単なスクリプトを作成しようとしています。最初に readlines() を使用しようとしましたが、すべてのファイルがメモリに読み込まれ、インスタンスには 28 GB のメモリしかありません。sizehint パラメーターを使用すると、ファイルの一部のみが解析されます。

私は今、ファイルを繰り返し処理しています。問題は、テキスト解析の出力を 3 つのリストに格納すると、かなり大きくなり、使用可能なメモリが不足することです。これはスワップの使用に切り替わるだけだと思っていましたが、それは問題ありませんが、代わりに「MemoryError」で終了します。

これは小さなサンプル ファイルでは問題なく機能しますが、実際のデータでは機能しません。

スクリプト:

import sys

a = []
b = []
c = []

file1 = open(sys.argv[1],"r")
for line in file1:
    if '@' in line:
        a.append(line.lstrip('@').rstrip('\n'))
        b.append(file1.next().rstrip('\n'))
file1.close()

file2 = open(sys.argv[2],"r")
for line in file2:
    if '@' in line: 
        c.append(file2.next().rstrip('\n'))
file2.close()

file3 = open(sys.argv[3],"w")
for i in xrange(len(a)):
    file3.write("".join([">",a[i],'\n',b[i],":",c[i],"\n"]))

私がオンラインで見つけたものは、変数を格納するためのある種のデータベースを作成することを提案していますが、それは必須ではありません。これにどのように対処すればよいか、何か考えはありますか?

完全を期すために、これが私がやろうとしていることです (サンプルのテストデータから:

file1: 

@Read.Salmonella_paratyphi_A_chromosome.29004.4835/1
TCGTGTACAGCATTCTTTATAGTGGAACGGTGACCGTACCGCAAAGCTGCGAAATCAACGCCGGACKIPPTCGTAG
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

file2:

@Read.Salmonella_paratyphi_A_chromosome.29004.4835/1
TCGTGTACAGCATTCTTTATAGTGGAACGGTGACCGTACCGCAAAGCTGCGAAATCAACGCCGGACAAACGATTCT
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

file3 (output):

>Read.Salmonella_paratyphi_A_chromosome.29004.4835/1
TCGTGTACAGCATTCTTTATAGTGGAACGGTGACCGTACCGCAAAGCTGCGAAATCAACGCCGGACKIPPTCGTAG:TCGTGTACAGCATTCTTTATAGTGGAACGGTGACCGTACCGCAAAGCTGCGAAATCAACGCCGGACAAACGATTCT
4

3 に答える 3

1

ファイルを配列(、、および)に解析する代わりに、ファイルを解析するときにファイルにa書き込むbことcができますか?

この疑似的なコードのようなもの:

def get_line_with_at(a):
     while a:
         line = a.readline()
         if "@" in line:
             return line.strip()


# Open all file handles
a, b, c = [open(sys.argv[x + 1]) for x in range(3)]
out = open(sys.argv[4])

while a and b and c:
    # Repeat until a, b, and file handles are exhausted
    chunk1 = get_line_with_at(a)
    chunk2 = b.next().strip()
    chunk3 = get_line_with_at(c)

     out.write(
         ">%s\n%s:%s\n" % (chunk1, chunk2, chunk3))

そうすれば、メモリにロードする必要があるのはごくわずかです(理論的には4つのファイルハンドルと現在の行の内容)

于 2012-07-16T16:49:59.593 に答える
0

私はこれを自分で試したことがありませんが、次のように動作するはずです。

file1 = open(sys.argv[1],"r")
file2 = open(sys.argv[2],"r")
file3 = open(sys.argv[3],"w")

for line1 in file1:
    if '@' in line1:  # line1.startswith('@') is probably better here
        a=line1.lstrip('@').rstrip('\n')
        b=file1.next().rstrip('\n')
        for line2 in file2:
            if '@' in line2:
                c=file2.next().rstrip('\n')
                break
        file3.write(">%s\n%s:%s\n"%(a,b,c))

file1.close()
file2.close()
file3.close()

この場合、ファイルごとに一度に1行だけメモリに保持します...ファイルに本当に長い行がない限り、これで問題ありません; ^)。

また、lstrip「@」文字を使用しているため、。if line.startswith('@')の代わりに使用することを検討することをお勧めしますif '@' in line

于 2012-07-16T16:51:42.013 に答える
0

これが私の[2番目の、よりコンパクトな]取り組みです。

import sys
import itertools

def reader(fileobj, yield_at_line=False):
    for line in fileobj:
        if line.startswith('@'):
            at_line = line.lstrip('@').rstrip('\n')
            next_line = fileobj.next().rstrip('\n')
            yield (at_line, next_line) if yield_at_line else next_line

with open(sys.argv[1]) as file1, open(sys.argv[2]) as file2, open(sys.argv[3], "w") as file3:
    first = reader(file1, yield_at_line=True)
    second = reader(file2)
    for (a,b), c in itertools.izip(first, second):
        file3.write('>{}\n{}:{}\n'.format(a, b, c))

を与える

~/coding$ cat file1
@Read.Salmonella_paratyphi_A_chromosome.29004.4835/1
TCGTGTACAGCATTCTTTATAGTGGAACGGTGACCGTACCGCAAAGCTGCGAAATCAACGCCGGACKIPPTCGTAG
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

~/coding$ cat file2
@Read.Salmonella_paratyphi_A_chromosome.29004.4835/1
TCGTGTACAGCATTCTTTATAGTGGAACGGTGACCGTACCGCAAAGCTGCGAAATCAACGCCGGACAAACGATTCT
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

~/coding$ python simulwork.py file1 file2 file3
~/coding$ cat file3
>Read.Salmonella_paratyphi_A_chromosome.29004.4835/1
TCGTGTACAGCATTCTTTATAGTGGAACGGTGACCGTACCGCAAAGCTGCGAAATCAACGCCGGACKIPPTCGTAG:TCGTGTACAGCATTCTTTATAGTGGAACGGTGACCGTACCGCAAAGCTGCGAAATCAACGCCGGACAAACGATTCT
于 2012-07-16T16:57:07.373 に答える