web-dev-qa-db-ja.com

ファイルをチャンクで読み取る-RAM使用量、バイナリファイルから文字列を読み取る

rAMの違いを理解したい-Pythonで大きなファイルを読み取るときのこのメソッドの使用法。

ここにstackoverflowで見つかったバージョン1:

def read_in_chunks(file_object, chunk_size=1024):
    while True:
        data = file_object.read(chunk_size)
        if not data:
            break
        yield data


f = open(file, 'rb')
for piece in read_in_chunks(f):
    process_data(piece)          
f.close()

バージョン2、上記のコードを見つける前にこれを使用しました:

f = open(file, 'rb')
while True:
    piece = f.read(1024)      
    process_data(piece)        
f.close()

ファイルは両方のバージョンで部分的に読み取られます。そして、現在のピースを処理することができます。 2番目の例では、pieceがすべてのサイクルで新しいコンテンツを取得しているので、これでnot完全にロードされないようになります。ファイルをメモリに..?

しかし、私はyieldが何をするのか本当に理解しておらず、ここで何か問題が発生したと確信しています。誰かが私にそれを説明できますか?


使用された方法以外に、私を困惑させる何かがあります:

私が読んだ作品の内容は、上記の例ではチャンクサイズ1KBで定義されています。しかし...ファイル内の文字列を探す必要がある場合はどうなりますか? "ThisIsTheStringILikeToFind"のようなもの?

ファイル内のどこに文字列が含まれているかによって、1つの部分に"ThisIsTheStr"が含まれ、次の部分に"ingILikeToFind"が含まれる可能性があります。このような方法を使用すると、どの部分でも文字列全体を検出することはできません。

ファイルをチャンクで読み取る方法はありますが、どういうわけかそのような文字列を気にしますか?

どんな助けやアイデアも大歓迎です、

挨拶!

11
xph

yieldは、ジェネレータ式に使用されるpythonのキーワードです。つまり、次に関数が呼び出される(または繰り返される)ときに、実行は正確にバックアップされます。 2つの関数は同じように動作しますが、唯一の違いは、最初の関数が2番目の関数よりもわずかに多くの呼び出しスタックスペースを使用することです。ただし、最初の関数ははるかに再利用可能であるため、プログラムからデザインの観点から、最初のものが実際に優れています。

編集:また、もう1つの違いは、最初のデータはすべてのデータが読み取られると読み取りを停止しますが、2番目のデータはf.read()またはprocess_data()のいずれかで1回だけ停止することです。例外をスローします。 2番目のものを正しく機能させるには、次のように変更する必要があります。

f = open(file, 'rb')
while True:
    piece = f.read(1024)  
    if not piece:
        break
    process_data(piece)
f.close()
19
AJMansfield

これを行うためのおそらく最良かつ最も慣用的な方法は、組み込みの iter() 関数をsentinel以下に示すように、反復可能オブジェクトを作成して使用するための値。ファイルサイズが正確な倍数でない場合、最後のチャンクが要求されたチャンクサイズよりも小さくなる可能性があることに注意してください。

from functools import partial

CHUNK_SIZE = 1024
filename = 'testfile.dat'

with open(filename, 'rb') as file:
    for chunk in iter(partial(file.read, CHUNK_SIZE), b''):
        process_data(chunk)
1
martineau