あなたが持っているかもしれないし持っていないかもしれないいくつかのライブラリを使って、私は大まかにこのようなPythonコードをいくつか持っています:
# Open it for writing
vcf_file = open(local_filename, "w")
# Download the region to the file.
subprocess.check_call(["bcftools", "view",
options.truth_url.format(sample_name), "-r",
"{}:{}-{}".format(ref_name, ref_start, ref_end)], stdout=vcf_file)
# Close parent process's copy of the file object
vcf_file.close()
# Upload it
file_id = job.fileStore.writeGlobalFile(local_filename)
基本的に、データをダウンロードして標準出力に出力するサブプロセスを開始しています。そのデータをファイルにリダイレクトし、サブプロセス呼び出しが戻るとすぐに、ファイルへのハンドルを閉じて、ファイルを別の場所にコピーします。
私が期待しているデータの最後尾がコピーに含まれていない場合があることを観察しています。今、時々そのデータを書き込んでいない可能性がありますが、安全でないことをしていて、が戻った後、子プロセスが標準出力に書き込むデータが作成される前にbcftools
、何らかの方法でファイルにアクセスできるのではないかと心配しています。私が見ることができるディスクに。subprocess.check_call()
C 標準を見ると (bcftools は C/C++ で実装されているため)、プログラムが正常に終了すると、開いているすべてのストリーム (標準出力を含む) がフラッシュされて閉じられるように見えます。戻り時に暗黙的に呼び出されるの動作について説明している、こちら[lib.support.start.term]
のセクションを参照してください。exit()
main()
--次に、未書き込みのバッファリングされたデータを含むすべての開いている C ストリーム (で宣言されている関数シグネチャによって仲介される) がフラッシュされ、開いているすべての C ストリームが閉じられ、tmp-file() の呼び出しによって作成されたすべてのファイルが削除されます.30)
-- 最後に、制御がホスト環境に戻されます。status が 0 または EXIT_SUCCESS の場合、成功した終了ステータスの実装定義形式が返されます。ステータスが EXIT_FAILURE の場合、ステータスの失敗した終了の実装定義形式が返されます。それ以外の場合、返されるステータスは実装定義です.31)
したがって、子プロセスが終了する前に、標準出力を閉じます (したがって、フラッシュします)。
ただし、Linuxのマニュアル ページclose(2)
では、ファイル記述子を閉じても、それに書き込まれたデータが実際にディスクに書き込まれたことを必ずしも保証しないことに注意してください。
カーネルが書き込みを遅延させるため、クローズが成功しても、データがディスクに正常に保存されたことは保証されません。ストリームが閉じられたときにファイルシステムがバッファをフラッシュすることは一般的ではありません。データが物理的に保存されていることを確認する必要がある場合は、fsync(2) を使用してください。(この時点では、ディスク ハードウェアによって異なります。)
したがって、プロセスが終了すると、その標準出力ストリームがフラッシュされるように見えますが、そのストリームがディスク上のファイルを指すファイル記述子によって実際にバックアップされている場合、ディスクへの書き込みが完了したとは限りません。それがここで起こっていることかもしれないと思います。
だから、私の実際の質問:
私の仕様の読みは正しいですか?リダイレクトされた標準出力がディスク上で利用可能になる前に、子プロセスが親に終了したように見えることがありますか?
子プロセスによってファイルに書き込まれたすべてのデータが実際に OS によってディスクに同期されるまで、何らかの方法で待機することは可能ですか?
親プロセスのファイルオブジェクトのコピーで、
flush()
またはPythonバージョンを呼び出す必要がありますか?fsync()
子プロセスによる同じファイル記述子への書き込みを強制的にディスクにコミットできますか?