15

20Gbのファイルを解析して、ある条件を満たす行を別のファイルに出力しているのですが、pythonが2行を一度に読み込んで連結してしまうことがあります。

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 マークのあたりです。

4

2 に答える 2

23

「python reading files large than 4gb」をグーグルですばやく検索すると、多くの結果が得られました。そのような例 と、最初の から引き継ぐ別の例については、こちらを参照してください。

Python のバグです。

さて、バグの説明; 内部 FILE バッファ サイズと fread() に渡される文字数の両方に依存するため、再現するのは簡単ではありません。Microsoft CRT ソース コードの open.c には、次の励ましのコメントで始まるブロックがあります。 " 奇妙なことに、 Perlソース コードにこの関数のほぼ正確なコピーがあります。 問題は SetFilePointer() の呼び出しにあります。これは、先読みの後に 1 つ前の位置に戻るために使用されます。32 ビット DWORD で現在の位置を返すことができないため、失敗します。[修正は簡単です。] この時点で、関数は次の read() が LF を返すと考えていますが、ファイル ポインタが戻されていないため、返されません。

そして回避策:

ただし、Python 3.x は影響を受けないことに注意してください (生ファイルは常にバイナリ モードで開かれ、CRLF 変換は Python によって行われます)。2.7 では、io.open() を使用できます。

于 2012-04-19T02:53:01.427 に答える
7

4GB マークは、疑わしいことに、32 ビット レジスタに格納できる最大値 (2**32) に近いです。

あなたが投稿したコード自体は問題ないように見えるので、あなたの Python ビルドにバグがあるのではないかと思います。

FWIW、 enumerateを使用すると、スニペットは少しきれいになります:

inputFileHandle = open(inputFileName, 'r')

for row, line in enumerate(inputFileHandle):
    if line_meets_condition:
        outputFileHandle.write(line)
    else:
        lstIgnoredRows.append(row)
于 2012-04-19T02:45:17.273 に答える