2012-03-22 9 views
15

私はテストを行っていますが、プログラムを中止するためにcontrol-Cを実行するまで、実際にファイルが書き込まれないことがわかりました。なぜそれが起こるのか誰も説明できますか?プログラムを停止するまでファイルが書き込まれないのはなぜですか?

私はそれが同時に書くことを期待していたので、プロセスの途中でファイルを読むことができました。

import os 
from time import sleep 

f = open("log.txt", "a+") 
i = 0 
while True: 
    f.write(str(i)) 
    f.write("\n") 
    i += 1 
    sleep(0.1) 
+0

日時:http://stackoverflow.com/questions/を参照してください、「理由を説明します」 1450551/buffered-io-vs-unbuffered-io –

答えて

49

ディスクへの書き込みが遅いため、多くのプログラムでは書き込みが大きなチャンクに書き込まれ、一括書き込みが行われます。これはというバッファリングと呼ばれ、ファイルを開くとPythonが自動的に行います。

ファイルに書き込むと、実際にはメモリ内の「バッファ」に書き込んでいます。いっぱいになると、Pythonはそれを自動的にディスクに書き出します。おそらくバッファリングするオペレーティングシステムは、同様に書き込みますので、それは、

f.flush() 

これはかなり全体の話ではないと「今、ディスクにバッファ内のすべてのものを書く」伝えることができます。あなたはopen(f, "w", 0)で特定のファイルをバッファリングしないのPythonを伝えることができるかだけopen(f,"w", 1)で1行のバッファを維持するために、最後に

os.fsync(f.fileno()) 

でファイルのバッファを書き込むために、それを伝えることができます。当然、書き込みが遅いため、これはそのファイルのすべての操作を遅くします。

+0

+1本当に有益な情報 – twneale

+4

無償の 'fsync()'は、スピン・ディスク・ドライブを搭載したラップトップを持ち、バッテリー寿命を気にしている人々の悩みです。コンテンツを他のプログラムから見えるようにするには 'fsync()'を呼び出す必要はありません。予期しない再起動後に視認性に近づいています(必ずしも十分な条件ではありませんが)。 –

+0

@CharlesDuffy: '他のプログラムにコンテンツを見せるためにfsync()を呼び出す必要はありません.'なぜですか?私はあなたのプログラムが終了しておらず、他のプログラムがファイルを読み込んだ場合、その内容は更新されない可能性があると思います。 –

5

ファイル書き込みバッファをファイルに書き出すには、f.close()にする必要があります。または、あなたの場合は、f.flush(); os.fsync();を実行するだけで、開いているファイルハンドルをループし続けることができます。

import osを忘れないでください。

+0

...または 'f.flush()' –

+1

実際には、これはos.fsync()なしでディスクへの書き込みを保証しません – deed02392

+1

それが他のプログラムに見える場合は、彼がここで求めているものです。 os.fsync()は高価なもので、必要なことがわかっていない限り(通常はユーザーがオフにする方法がある)、使用されるべきではありません。ほとんどのデータベースでもfsyncを無効にする方法があることに注意してください。ユーザーがデータ破損の危険を冒して物事を速くしたいと思うことがあります。 –

1

あなたはfile.flush()をチェックアウトしたくなるでしょう - これはないは、ディスクにデータを書き込む可能性があることに注意して取るものの、引用する:

注: フラッシュ()は必ずしもにファイルのデータを書き込みませんディスク。この動作を保証するには、flush()の後にos.fsync()を使用します。

ファイル(file.close())もデータが書き込まれていることを保証します閉じる - 暗黙のうちにこれを行いますwithを使用して、そしてより多くの読みやすさと明確さのためのより良い選択が一般的である - ない他の潜在的な問題を解決するに言及しています。

0

これはウィンドウのアイムです。ファイルを終了したときに明示的に.close()を追加すると、その時点でエクスプローラに表示されます。単にそれを洗うことでさえ十分かもしれません(私はテストするのに便利な窓の箱がありません)。しかし、基本的にf.write は、実際にはを書きません。書き込みバッファに追加するだけです。バッファがフラッシュされるまで表示されません。

UNIXの場合、ファイルは通常この状況では0バイトのファイルとして表示されます。

0

フラッシュするファイルハンドラ。ガベージコレクションが有効になると、I/Oバッファ(f.close()を呼び出すことによって可能性が高い以上)をフラッシュするまで、出力バッファがフラッシュになっていないよう

f.flush() 
0

ファイルは、書き込まれません。

ループ内ではf.flush()の後にos.fsync()と、hereのように呼び出すことができます。

f.flush() 
os.fsync() 

あなたがあなたのコードの他の部分と、そのファイル内のデータを共有する場合すべてのことが言われているが、私は非常にStringIOオブジェクトを使用することをお勧めします。

1

あなたが書き込みを強制しなければならないので、私は、私は、ファイルが書き込まれていることを確認するために以下の行を使用します。

# Two commands together force the OS to store the file buffer to disc 
    f.flush() 
    os.fsync(f.fileno()) 
関連する問題