2017-04-10 12 views
4

私は8Gのヒープスペースしか利用できず、それよりも大きなファイルを一連の小さなファイルに分割したいと考えています。試してみたらメモリよりも大きなファイルを分割するには?

with open(fname) as f: 
    content = f.readlines() 

ファイル全体を読み込もうとするため、メモリが不足します。メモリにすべてのものをロードせずにファイルを開く方法はありますか?

+1

'を反復ではなく' readlines()とファイル全体を読み取るF' ' – jordanm

+1

は、その場合の反復の各単位は何ですか? – amphibient

+0

これは重複している可能性があります:http://stackoverflow.com/questions/2363483/python-slicing-a-very-large-binary-file –

答えて

1

itertools.islice仕事のための優れたツールですが、あなたは効率的にそれを使用する方法を検討する必要があります。たとえば、islice(f, 10, 20)は10行を破棄してから20行を放棄するので、書き込みを行うには良い方法ではありません。ループの書き方によっては、書き込みごとにデータを破棄したり、ファイルを再スキャンしたりすることができます。

あなたが完了したときにそのことも分かりません。 fileobj.writelines(isslice(f, 10))は、時間の終わりまで0行のファイルを楽しく書くでしょう。あなたは実際にあなたが事実の後に行われていることを知っているだけなので、長さがゼロのファイルを書き終わったらテストできます。

この例では、大きなファイルの長さが100行で、10行に分割されています。これは8ギガバイトのファイルよりもテストが少し速いです。

import itertools 
import os 

lines_per_file = 10 

with open('big.txt') as infp: 
    # file counter used to create unique output files 
    for file_count in itertools.count(1): 
     out_filename = 'out-{}.txt'.format(file_count) 
     with open(out_filename, 'w') as outfp: 
      # write configured number of lines to file 
      outfp.writelines(itertools.islice(infp, lines_per_file)) 
     # break when no extra data written 
     if os.stat(out_filename).st_size == 0: 
      os.remove(out_filename) 
      break 
+0

RE: "あなたが完了した時を知ることは明らかではありません" - まさに私が他の答えにコメントしていた理由 "どのように私がEOFに達したかを知っていますか? – amphibient

2

ファイルハンドルは、ファイル内の行のイテレータとして使用できます。あなたが望むのは、そのイテレータの特定のスライスです。標準ライブラリには便利なitertools.islice()関数があります。

from itertools import islice 

line_slice = (10, 20) 
with open(fname) as f: 
    content = islice(f, *line_slice) 

上記は、f.readlines()[10:20]と多かれ少なかれ同等です。

islice()の出力が別のイテレータであることに注意してください。幸いなことに、writelines()はイテレータを受け入れますので、一時的なリストに変換する必要はありません。これは事実上、writelines()に直接渡すと、いつでもメモリ内に複数の行を保持しないことを意味します。

with open(out_fname, 'w') as f: 
    f.writelines(content) 
+0

メソッドとパラメータの簡単な説明を書いてください。 –

+0

しかし、アプローチは良いようですが、どのようにしてEOFに達したのか分かりますか?それは例外を投げません – amphibient

関連する問題