2013-05-29 10 views
5

私は設定ファイルと対話するライブラリを持っています。ライブラリがインポートされると、初期化コードは設定ファイルを読み込み、おそらくそれを更新し、更新された内容をファイルに書き戻します(何も変更されていなくても)。Pythonはいつファイルをディスクに書き出しますか?

非常に時折、設定ファイルの内容が消えるという問題が発生します。具体的には、これは短いスクリプト(ライブラリを使用して)を何度も繰り返し実行したときに発生します。同じディレクトリの中で決して起こることはありません。それは、それが若干ランダムな問題、具体的にはI/Oの競合状態であると信じさせています。

これは問題を確実に再現することはできず、一部のシステムでのみ発生するため、これはデバッグするのに苦労します。私は何が起こるのか疑問を呈していますが、私はPythonでファイルI/Oの画像が正しいかどうかを見たいと思っていました。

質問:Pythonプログラムは実際にファイルの内容をディスクに書き込むのはいつですか?ファイルが閉じた時点で内容がディスクになると思っていましたが、このエラーを説明できません。 Pythonがファイルを閉じるときに、内容をディスク自体にフラッシュするのか、それとも単にファイルシステムにキューイングするのでしょうか? Pythonの終了後にファイルの内容をディスクに書き込むことは可能でしょうか?そして、fp.flush(); os.fsync(fp.fileno())fpはファイルハンドルです)を使用してこの問題を回避できますか?

私はUnixシステム(特にMac OS X)でプログラミングしています。 編集:また、プロセスが同時に実行されていないことに注意してください。

付録:ここでは、私は疑う特定の競合状態です:

  1. プロセス#1が起動されます。
  2. プロセス#1は、コンフィギュレーションファイルを読み取りモードで開き、終了すると閉じます。
  3. プロセス#1は、コンフィギュレーションファイルを書き込みモードで開き、すべての内容を消去します。内容の消去は、ディスクに同期されます。
  4. プロセス#1は新しい内容をファイルハンドルに書き込み、それを閉じます。
  5. プロセス#1:ファイルを閉じると、PythonはOSに、これらの内容をディスクに書き込むようにキューに入れるように指示します。
  6. プロセス#1が閉じて、
  7. プロセス#2を出て呼び出さ
  8. プロセス#2で読み取りモードで設定ファイルを開きますが、新しい内容はまだ同期されません。プロセス#2は空のファイルを見る。
  9. プロセス2がファイルを読み取った後、OSは最終的にディスクに内容の書き込みを終了します。
  10. プロセス2は、ファイルが空であると考えて、構成ファイルのデフォルトを設定します。
  11. プロセス#2は、コンフィギュレーションファイルのバージョンをディスクに書き込み、最後のバージョンを上書きします。
+5

いいえ、Pythonがファイルを閉じると、ファイルはディスクにフラッシュされていません。私はあなたが思うよりも早くプロセス#2がファイルを開くと言うでしょう。 –

+2

複数のプロセスが同時にファイルにアクセスし、少なくとも1つがそのプロセスに書き込む場合は、プロセスを同期させて一貫した結果を得る必要があります。これはPython固有のものではありません。 –

+2

OSがデータをディスクに書き込まなくても、そのファイルにアクセスする誰かが共有するメモリキャッシュがあるため、Pythonからフラッシュされている限り、ファイルの内容を2.プロセスに返すことが保証されます。 (一貫性のために構成されていない共有ファイルシステム上の別のマシン上でプロセスを実行している場合や、ファイルを上書きする競合状態が発生している場合を除く) – nos

答えて

1

ほとんどの場合、Pythonの欠陥ではありません。 pythonがファイルを閉じると、ORが正常に終了します(信号で殺されるのではなく)、OSはファイルの新しい内容を持ちます。それ以降のオープンは新しい内容を返すべきです。何かもっと複雑なことがなければなりません。ここにいくつかの考えがあります。あなたが記述何

  1. はPythonのバグよりもファイルシステムのバグである可能性が高いサウンド、およびファイルシステムのバグはかなり低いです。

  2. ファイルシステムが実際にリモートファイルシステムに存在する場合、ファイルシステムのバグははるかに高い可能性があります。彼らは?

  3. すべてのプロセスで同じファイルが使用されていますか?ファイルの "ls -li"を実行して、そのiノード番号を確認し、変更されているかどうかを確認します。あなたのシナリオでは、そうしてはいけません。ファイルの移動やディレクトリの移動、ディレクトリの削除、再作成が可能なのでしょうか?シンボリックリンクは関係していますか?

  4. あなたのプログラムの実行中に重複はありませんか?それらのうちのどれかが末尾(つまりバックグラウンド)に "&"のシェルから実行されていますか?これは、最初のものが終了する前に2番目のものが開始されたことを容易に意味する可能性があります。

  5. 同じファイルに書き込むプログラムはありますか?

  6. これはあなたの質問ではありませんが、アトミックな変更が必要な場合(並列で実行されるすべてのプログラムが古いバージョンまたは新しいバージョンのいずれかしか表示されないように、空のファイルはありません)新しいコンテンツを別のファイル(たとえば "foo.tmp")に書き込んだ後、os.rename( "foo.tmp"、 "foo")を実行します。名前の変更はアトミックです。

+0

これは私が望むことができる最高の答えです。ありがとうございました! – HardlyKnowEm

+0

明らかになったように、インターンはライブラリ関数を編集して、別のPythonサブプロセス(同じモジュールを使用)を生成していました。その変更をロールバックした後、問題は消え去っていたようです。それはおそらく問題がインターンのコンピュータでのみ起こった理由も説明します。 – HardlyKnowEm

+0

あなたはそれを理解してうれしい! –

関連する問題