Pythonのfile.flush()は正確には何をしているのですか?


137

私はこれをファイルオブジェクトの Python ドキュメントで見つけました:

flush()は、必ずしもファイルのデータをディスクに書き込むとは限りません。この動作を保証するには、flush()に続けてos.fsync()を使用します。

だから私の質問は:Pythonは正確には何をしflushているのですか?ディスクへのデータの書き込みが強制されると思いましたが、今はそうではないことがわかりました。どうして?

回答:


219

通常、2つのレベルのバッファリングが含まれます。

  1. 内部バッファ
  2. オペレーティングシステムバッファ

内部バッファは、プログラミング対象のランタイム/ライブラリ/言語によって作成されたバッファであり、すべての書き込みに対するシステムコールを回避することで、処理を高速化することを目的としています。代わりに、ファイルオブジェクトに書き込むときは、そのバッファーに書き込みます。バッファーがいっぱいになると、データはシステムコールを使用して実際のファイルに書き込まれます。

ただし、オペレーティングシステムのバッファが原因で、これはデータがディスクに書き込まれることを意味しない場合があります。これは、ランタイムによって維持されているバッファからオペレーティングシステムによって維持されているバッファにデータがコピーされることを意味するだけかもしれません。

何かを書き込んで、それがバッファ(のみ)に到達し、マシンの電源が切れた場合、マシンの電源を切ると、そのデータはディスク上にありません。

だから、助けるためにあなたが持っているとflushし、fsyncに、それぞれのオブジェクトにメソッドがあります。

1つ目flushは、プログラムバッファーに残っているデータを実際のファイルに書き込むだけです。通常、これはデータがプログラムバッファーからオペレーティングシステムバッファーにコピーされることを意味します。

具体的には、これは、別のプロセスが同じファイルを読み取り用に開いている場合、そのファイルにフラッシュしたばかりのデータにアクセスできることを意味します。ただし、必ずしも「永続的に」ディスクに保存されているという意味ではありません。

これを行うには、os.fsyncすべてのオペレーティングシステムバッファーが対象のストレージデバイスと同期していることを確認するメソッドを呼び出す必要があります。つまり、このメソッドは、オペレーティングシステムバッファーからディスクにデータをコピーします。

通常、どちらの方法でも気にする必要はありませんが、実際にディスク上で何が発生するかについての妄想が良い状況にある場合は、指示どおりに両方の呼び出しを行う必要があります。


2018年の補遺。

キャッシュメカニズムを備えたディスクが2013年よりもはるかに一般的になったため、今ではさらに多くのレベルのキャッシュとバッファーが含まれていることに注意してください。私は仮定し、これらのバッファが同様に同期/フラッシュの呼び出しによって処理されますが、私は本当に知りません。


10
with file('blah') as fd: #dostuff構造体を使用すると、ファイル記述子を確実に閉じることがわかります。また、フラッシュまたは同期しますか?
Marcin、

3
@Marcin:フラッシュしますが、同期しません。
Alex I

8
fsync原子性のために必要です。ファイルを閉じてから再度開いてfsync、途中にa がないコンテンツを見つけることはできません。これはしばしば機能しますが、例えばext4とデフォルトのマウントオプションを備えたLinuxでは機能しません。また、fsyncハードディスクの内部バッファリングがフラッシュに指示されない場合があります。FSYNCが(ラップトップモードで)無効にすることができ、そして2:本当にマグネットフリップ1ので、プラッタ上の鉄を保証するものではありません。
v.oddou

1
ファイルが別のプロセスによって書き込まれた場合、オペレーティングシステムのバッファをすべてのファイルに対してフラッシュする方法はありますか?
2014

1
fsyncは比較的高価です。一般的に、ディスクアクセスに100%ACIDコンプライアンスと耐久性を必要とするミッションクリティカルなソフトウェアを作成しているわけではありません。そうした場合、おそらくそれを痛切に認識しており、これらの保証を取得するために実行できる手順を認識しているはずです。 。fsyncを呼び出すと、物理ディスクアクセスが発生してデータがディスクに書き込まれるのを待ちますが、フラッシュとクローズでは、データがキャッシュメモリに移動されるのを待つだけです。速度の違いはおそらく数桁です。
ラッセV.カールセン

10

オペレーティングシステムがそうしない可能性があるためです。フラッシュ操作により、ファイルデータがRAMのファイルキャッシュに強制的に送られ、そこから実際にディスクに送信するのはOSの仕事です。


6
その通りですが、actuallyここでは相対的です。ターゲットデバイスで書き込みキャッシュが有効になっている場合、データがos.fsync()戻ったときに実際のプラッター/チップにデータが到達していない可能性があります。
フレデリックハミディ2011

7

内部バッファをフラッシュします。これにより、OSがバッファをファイルに書き込みます。[1] Pythonは、特に構成しない限り、OSのデフォルトのバッファリングを使用します。

ただし、OSがまだ協力しないことを選択する場合もあります。特に、Windows / NTFSでの書き込み遅延などの素晴らしい機能を備えています。基本的に、内部バッファはフラッシュされますが、OSバッファはまだそれを保持しています。したがってos.fsync()、それらの場合には、ディスクに書き込むようにOSに指示する必要があります。

[1] http://docs.python.org/library/stdtypes.html


0

基本的に、flush()はRAMバッファーをクリーンアップします。その真の力は、後で書き込みを続行できることです。来るべきより多くのデータのためにあなたのRAMをフラッシュしています、それがすべてです。データが安全にファイルに書き込まれるようにしたい場合は、代わりにclose()を使用してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.