2012-04-19 4 views
15

私は20Gbファイルを解析して特定の条件を満たす行を別のファイルに出力しますが、時にはpythonは2行を同時に読み込み、それら。pythonで大きな(20GB)テキストファイルを解析する - 2行を1として読み込む

inputFileHandle = open(inputFileName, 'r') 

row = 0 

for line in inputFileHandle: 
    row = row + 1 
    if line_meets_condition: 
     outputFileHandle.write(line) 
    else: 
     lstIgnoredRows.append(row) 

私はソースファイルの行末をチェックしており、改行(ascii char 10)としてチェックアウトしています。問題の行を引き出し、分離して解析することは、期待通りに機能します。私はここでいくつかのPythonの制限を打つのですか?最初の異常のファイル内の位置は4GBマークの周りです。

+0

拳の異常は常に同じ行数で一貫して発生しますか?また、 'lstIgnoredRows'はリストで、その大きさはどれくらい大きくなりますか?私はあなたが出力ファイルに興味のある行を保存し、無視したい行を何もしなかった場合にはどうなるのだろうかと思います。 – Levon

+1

おそらく、この質問と同様に、遅延メソッドを使用して、一度に小さなファイルのチャンクを読むことができますか?それはショットを与えるhttp://stackoverflow.com/questions/519633/lazy-method-for-reading-big-file-in-python – prrao

+0

毎回同じ行数で発生します。 lstIgnoredRowsは数千のアイテムに拡大できます。 – James

答えて

23

「4ギガバイト以上のファイルを読み込むパイソン」のクイックGoogle検索は多くの多くの結果が得られました。 here for such an exampleand another one which takes over from the firstを参照してください。

これはPythonのバグです。

ここで、このバグの説明。それは内部FILEバッファサイズとfread()に渡される文字数の両方に依存するので、再現するのは容易ではありません。 Microsoft CRTのソースコードopen.cには、この奨励的なコメントから始まるブロックがあります。 "これは難しい部分です。バッファの最後にCRがあります。次のcharがLF " 奇妙なことに、Perlのソースコードには、この関数のほぼ正確なコピーがあります。 http://perl5.git.perl.org/perl.git/blob/4342f4d6df6a7dfa22a470aa21e54a5622c009f3:/win32/win32.c#l3668 問題はLookAheadの後に1つの位置を後退させるために使用されるSetFilePointer()の呼び出しにあります。現在の位置を32ビットDWORDで返すことができないため、失敗します。 [修正は簡単です。あなたはそれを見ますか?] この時点で、関数は、次のread()がLFを返すと考えていますが、ファイルポインタが戻されなかったためではありません。

そして回避策:

しかし、(RAWファイルは常にバイナリモードで開かれ、CRLFの翻訳はPythonで行われている)のPython 3.xのが影響されないことに注意してください。 2.7では、io.open()を使用することができます。

+1

バイナリモードでファイルを開くとこの問題が修正されました。助けてくれてありがとう open(inputFileName、 'rb') – James

+0

バイナリモードで開くと、私のためにそれを解決しました。これは人生の節約になります! – tlamadon

7

4GBのマークは、32ビットレジスタ(2 ** 32)に格納できる最大値に疑いの余地があります。

あなたが投稿したコード自体は上手く見えるので、Pythonビルドのバグを疑うでしょう。

それは列挙使用した場合のスニペットは少しきれいになりFWIW、:

inputFileHandle = open(inputFileName, 'r') 

for row, line in enumerate(inputFileHandle): 
    if line_meets_condition: 
     outputFileHandle.write(line) 
    else: 
     lstIgnoredRows.append(row) 
関連する問題