2

サブプロセスを生成して完了するのを待つWindows上で実行されるPythonコードがいくつかあります。サブプロセスは適切に動作しないため、スクリプトはノンブロッキングのスポーン呼び出しを行い、サイドでプロセスを監視します。タイムアウトのしきい値に達すると、プロセスが停止したと想定して、プロセスが強制終了されます。

再現性のない場合によっては、生成されたサブプロセスが消えて、ウォッチャールーチンがこの事実を認識しなくなります。タイムアウトしきい値を超えるまで監視を続け、サブプロセスを強制終了してエラーを取得してから終了します。

サブプロセスがなくなってウォッチャープロセスが検出できなくなった原因は何でしょうか。の呼び出しによって戻りコードがトラップされて返されないのはなぜPopen.poll()ですか?

プロセスを生成して監視するために使用するコードは次のとおりです。

import subprocess
import time

def nonblocking_subprocess_call(cmdline):
    print 'Calling: %s' % (' '.join(cmdline))
    p = subprocess.Popen(cmdline, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    return p


def monitor_subprocess(handle, timeout=1200):
    start_time = time.time()
    return_code = 0
    while True:
        time.sleep(60)
        return_code = handle.poll()
        if return_code == None:
            # The process is still running.
            if time.time() - start_time > timeout:
                print 'Timeout (%d seconds) exceeded -- killing process %i' % (timeout, handle.pid)
                return_code = handle.terminate()
                # give the kill command a few seconds to work
                time.sleep(5)
                if not return_code:
                    print 'Error: Failed to kill subprocess %i -- return code was: %s' % (handle.pid, str(return_code))
                # Raise an error to indicate that the process was hung up
                # and we had to kill it.
                raise RuntimeError
        else:
            print 'Process exited with return code: %i' % (return_code)
            break
    return return_code

私が見ているのは、プロセスが消えた場合、return_code = handle.poll()15行目の呼び出しがNone戻りコードではなく戻ってきているということです。プロセスが完全になくなったことはわかっています。タスクマネージャーにはもう存在しないことがわかります。そして、タイムアウト値に達するずっと前にプロセスが消えたことを私は知っています。

4

3 に答える 3

1

サブプロセス オブジェクトの poll メソッドがうまく機能していないようです。仕事をするためにいくつかのスレッドを生成しているときに、同じ問題が発生していました。multiprocessing モジュールを使用することをお勧めします。

于 2012-11-08T23:24:21.090 に答える
1

cmdline 変数の例を教えてください。また、どのようなサブプロセスを生成していますか?

これをテスト スクリプトで実行し、次のコマンドでバッチ ファイルを呼び出しました。

ping -n 151 127.0.0.1>nul
  • 150秒間眠る

そしてそれはうまくいきました。

サブプロセスが正しく終了していない可能性があります。また、sleep コマンドを time.sleep(2) などに変更してみてください。

過去に、これはより長いスリープよりもうまく機能することがわかりました(特に、サブプロセスが別のpythonプロセスである場合)。

また、スクリプトにこれが含まれているかどうかはわかりませんが、else: ステートメントには余分な括弧があります。

else:
    #print 'Process exited with return code: %i' % (return_code))
    # There's an extra closing parenthesis
    print 'Process exited with return code: %i' % (return_code)
    break

そして、join ステートメントでグローバルな temp_cmdline が呼び出されているのはなぜですか。

print 'Calling: %s' % (' '.join(temp_cmdline))

cmdline がリスト変数 temp_cmdline から解析されているのか、それとも temp_cmdline がスペースで分割された文字列から作成されているのかはわかりません。いずれにせよ、cmdline 変数が文字列の場合、単に出力する方が理にかなっているでしょうか?

print 'Calling: %s' % cmdline
于 2012-11-08T22:55:19.350 に答える