2

この質問に触発されて、Python のopen()関数に対するオプションのバッファリング引数が何をするのか正確に知りたいと思っています。sourceを見ると、ストリームのバッファサイズを設定するためにbufferingが渡されていることがわかります(ドキュメントで確認されている のないシステムでは何もしません)。setvbufsetvbuf

ただし、ファイルを反復処理する場合、READAHEAD_BUFSIZE一度に読み取られるデータの量を定義するように見える と呼ばれる定数があります (この定数はここで定義されています)。

私の質問は、buffering議論が にどのように関係しているかREADAHEAD_BUFSIZEです。ファイルを反復処理する場合、一度にディスクから読み取られるデータの量を定義するのはどれですか? そして、これを明確にする C ソースの場所はありますか?

4

2 に答える 2

1

READAHEAD_BUFSIZEファイルをイテレータとして使用する場合にのみ使用されます

for line in fileobj:
    print line

freadこれは、 C API 呼び出しによって処理される通常のバッファー引数とは別のバッファーです。どちらも反復時に使用されます。

からfile.next():

forループをファイルの行をループする最も効率的な方法 (非常に一般的な操作) にするために、このメソッドnext()は非表示の先読みバッファを使用します。先読みバッファを使用した結果、next()他のファイル メソッド ( などreadline()) との組み合わせが正しく機能しません。ただし、 を使用seek()してファイルを絶対位置に再配置すると、先読みバッファがフラッシュされます。

OS バッファ サイズは変更されません。変更はsetvbuf、ファイルが開かれ、ファイル反復コードによって変更されないときに行われます。Py_UniversalNewlineFread代わりに、 (を使用する)への呼び出しをfread使用して先読みバッファを埋め、Python の内部に2 番目のバッファを作成します。それ以外の場合、Python は通常のバッファリングを C API 呼び出しに任せます (fread()呼び出しはバッファリングされます。リクエストを満たすためにユーザー空間バッファが参照されます。Pythonfread()はそれについて何もする必要はありません)。

readahead_get_line_skip()次に、このバッファから行 (改行で終了) を提供します。バッファに改行が含まれなくなった場合は、以前の値の 1.25 倍のバッファ サイズでそれ自体を再帰することにより、バッファを再充填します。これは、ファイル全体に改行文字がなくなった場合、ファイルの反復処理で残りのファイル全体をメモリ バッファーに読み込むことができることを意味します。

バッファの読み取り量を確認するには、fileobj.tell()ループ中にファイルの位置を ( を使用して) 出力します。

>>> with open('test.txt') as f:
...     for line in f:
...         print f.tell()
... 
8192   # 1 times the buffer size
8192
8192
~ lines elided
18432  # + 1.25 times the buffer size
18432
18432
~ lines elided
26624  # + 1 times the buffer size; the last newline must've aligned on the buffer boundary
26624
26624
~ lines elided
36864  # + 1.25 times the buffer size
36864
36864

ディスクから実際に読み取られるバイト (ディスク上の実際の物理ファイルである場合) は、バッファーと内部先読みバッファーfileobjの間の相互作用だけに依存するわけではありません。fread()OS自体がバッファリングを使用している場合も同様です。ファイル バッファが使い果たされた場合でも、OS はシステム コールを提供して、物理ディスクにアクセスするのではなく、独自のキャッシュからファイルを読み取ることができます。

于 2013-04-13T19:04:55.707 に答える