入力ファイル全体をlist
としてメモリに丸呑みすることを回避することで、大幅な節約が可能になります。 行の。
具体的には、これらの行は、bytes
のピークメモリ使用量を伴うという点で、メモリ使用量に関してひどいものです。 ファイル全体のサイズに加えて、list
をオブジェクト化します。 ファイルの完全な内容を含む行の数:
file_content = obj['Body'].read().decode('utf-8').splitlines(True)
for line in file_content:
500万行の1GBASCIIテキストファイル(64ビットPython 3.3以降)の場合、これはちょうどのピークメモリ要件である約2.3GBです。 bytes
オブジェクト、list
、および個々のstr
slist
。処理するファイルのサイズの2.3倍のRAMを必要とするプログラムは、大きなファイルに拡張できません。
修正するには、元のコードを次のように変更します。
file_content = io.TextIOWrapper(obj['Body'], encoding='utf-8')
for line in file_content:
obj['Body']
怠惰なストリーミングに使用できるようです
これにより、両方が削除されます。 メモリからの完全なファイルデータのコピー。 TextIOWrapper
の使用 obj['Body']
を意味します (一度に数KBの)チャンクで遅延読み取りおよびデコードされ、行も遅延して繰り返されます。これにより、ファイルサイズに関係なく、メモリ需要が小さく、ほぼ固定された量に削減されます(ピークメモリコストは最長の行の長さに依存します)。
更新:
StreamingBody
のように見えます io.BufferedIOBase
を実装していません ABC。 独自のドキュメント化されたAPI
があります ただし、これは同様の目的で使用できます。 TextIOWrapper
を作成できない場合 あなたのために仕事をしてください(それを機能させることができれば、はるかに効率的で簡単です)、別の方法は次のようになります:
file_content = (line.decode('utf-8') for line in obj['Body'].iter_lines())
for line in file_content:
TextIOWrapper
の使用とは異なり 、ブロックの一括デコード(各行は個別にデコードされます)のメリットはありませんが、それ以外の場合は、メモリ使用量の削減という点で同じメリットが得られるはずです。