2016-10-03 4 views
0

私はDjangoベースのサーバを持っており、私は仕事の束をしているスクリプトを呼び出しています。私はPopenを使用しているので、これは非同期である必要があります。しかし、デバッグのために、stdoutとstderrをPIPEからファイルにリダイレクトしたいと思います。これが非同期パフォーマンスに影響しますか?Popenにファイルを渡しても、非同期で実行することはできますか?

はどうすればファイルが開き、Pythonスクリプト自体がすでに実行されたときに適切に閉じて確認する必要があります(とリターン・コールを行いました。)

答えて

1

Popenデフォルトで非同期に実行されます。

Popenオブジェクトを保存して後で照会することができます。すべてのことが必要とされているが、そのステータスは、例えば、チェックする必要があるまでpどこかに格納することです

p = subproccess.Popen(executable) 

# continue with other work 

p.poll() # returns None if p is still running, returncode otherwise 
p.terminate() # closes the process forcefully 

p.wait() # freezes the execution until process finishes - makes it synchronous 

より良い場所がない場合、開始されたプロセスのグローバルなリストで。

UPDATE

問題は、ファイルを開くPopenにそれを与えると、処理が終了すると、すべての参照を保持せずに、ファイルを閉じる方法のようです。

これは単にスレッドで行うことができます。

def run_process(executable, filename): 
    with open(filename, 'w') as f: 
     subprocess.Popen(executable, stdout=f).wait() 

Thread(target=run_process, args=(executable, filename)).start() 

はそれを実行し、それを忘れ。 run_processは、プロセスが終了してファイルを閉じるまでフリーズしますが、すべてが別のスレッドで発生します。

注:0120-djangoプロセスが終了したときにスレッドやプロセスが終了しない場合は、スレッドやプロセスに何が起こるか気にする必要はありません。

これを処理するために、覚えておくより複雑なスレッドを作成して、djangoが終了する前に停止することができます。プロセスを終了するか、完了するのを待つかもしれません...

+0

私はそれがデフォルトで非同期に実行されます知っているが、私は意味し、何が起こりますか? –

+0

@DylanLawrenceああ!ファイルは閉じられるまでオープンされたままになります(オープン(...)を使用しないでください)。一方、後で閉じることができるように、ファイル参照をいくらか保存しておく必要があります。 – zvone

+0

その1つの問題は、これはウェブに面するアプリケーションなので、このスクリプトはクライアントを処理しており、サブプロセス呼び出しは基本的に「火と忘れ」です。変数を保持しないと、osはクリーンアップを処理しますか? –

1

これは、プログラムがどのように非同期である必要があるかによって異なります。 stdoutへの書き込みは、通常は高速ですが、データがディスクにフラッシュされるのを待つことがあるオペレーティングシステムのファイルキャッシュに移動します。通常これは問題ではありません。

stdoutはコンソールではないので、バッファリングされた書き込みを行い、プログラムがパイプのフラッシュをスキップする非標準エラーに遭遇すると問題になります。バッファリングはファイル内のものを遅らせることもできます。そのため、ファイルを参照している外部プログラムがすぐにログを見ることができません。

親プロセスは、子プロセスを開始した後にファイルのビューを閉じる必要があり、プロセスが終了するとオペレーティングシステムがファイルをクローズします。私はfはPythonのファイルオブジェクトであるSTDOUT = Fをすれば、サブプロセスがまだ実行されている間、Pythonは、参照のファイルの枠を離れた場合

with open('stdout', 'w') as out, open('stderr', 'w') as err: 
    proc = subprocess.Popen(['myprog'], stdout=out, stderr=err) 
+0

これで、 'with'を使ってもPythonスクリプトの実行は保持されません。 –

+0

親スクリプト?いいえ、フルスピードで動作します。子がファイルハンドルを開始し、親がループから完全に外れたときにファイルハンドルを子に渡しました。子の書き込みは、オペレーティングシステムのファイルキャッシュに直接送られます。 – tdelaney

+0

@tdelaney 'with'ブロックの最後に呼び出される' file.close() 'はファイルに影響しませんか? – zvone

関連する問題