28

Pythonで次のことを行う必要があります。プロセス (サブプロセス モジュール?) を生成したいのですが、次のようにします。

  • プロセスが正常に終了した場合は、終了した瞬間から正確に続行します。
  • それ以外の場合、プロセスが「スタック」し、(たとえば) 1 時間以内に終了しない場合は、プロセスを強制終了して続行します (おそらく、ループでもう一度試行します)。

これを達成するための最もエレガントな方法は何ですか?

4

5 に答える 5

33

モジュールはあなたのsubprocess友達になります。オブジェクトを取得するプロセスを開始し、Popen次のように関数に渡します。これはタイムアウト時にのみ例外を発生させることに注意してください。必要に応じて、例外をキャッチkill()し、プロセスでメソッドを呼び出すことができPopenます。(kill は Python 2.6 の新機能です)

import time

def wait_timeout(proc, seconds):
    """Wait for a process to finish, or raise exception after timeout"""
    start = time.time()
    end = start + seconds
    interval = min(seconds / 1000.0, .25)

    while True:
        result = proc.poll()
        if result is not None:
            return result
        if time.time() >= end:
            raise RuntimeError("Process timed out")
        time.sleep(interval)
于 2009-08-31T21:17:10.553 に答える
10

プロセスの PID がわかっていれば、psutilを使用してこれを行う方法が少なくとも 2 つあります。プロセスが次のように作成されていると仮定します。

import subprocess
subp = subprocess.Popen(['progname'])

...次のような忙しいループで作成時間を取得できます。

import psutil, time

TIMEOUT = 60 * 60  # 1 hour

p = psutil.Process(subp.pid)
while 1:
    if (time.time() - p.create_time()) > TIMEOUT:
        p.kill()
        raise RuntimeError('timeout')
    time.sleep(5)

...または単に、これを行うことができます:

import psutil

p = psutil.Process(subp.pid)
try:
    p.wait(timeout=60*60)
except psutil.TimeoutExpired:
    p.kill()
    raise

また、次の追加の API に興味があるかもしれません。

>>> p.status()
'running'
>>> p.is_running()
True
>>>
于 2012-05-10T18:19:37.207 に答える
4

同様の質問があり、この回答を見つけました。完全を期すために、一定時間後にハングしているプロセスを終了する方法をもう 1 つ追加したいと思います。Python シグナル ライブラリ https://docs.python.org/2/library/signal.html

ドキュメントから:

import signal, os

def handler(signum, frame):
    print 'Signal handler called with signal', signum
    raise IOError("Couldn't open device!")

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)

signal.alarm(0)          # Disable the alarm

とにかく新しいプロセスを生成したかったので、これは問題の最善の解決策ではないかもしれません.

于 2017-01-26T03:57:45.830 に答える
1

threading.Timer を使用してコールバック関数を設定することも、優れた受動的な方法です。

from threading import Timer

# execute the command
p = subprocess.Popen(command)

# save the proc object - either if you make this onto class (like the example), or 'p' can be global
self.p == p

# config and init timer
# kill_proc is a callback function which can also be added onto class or simply a global
t = Timer(seconds, self.kill_proc)

# start timer
t.start()

# wait for the test process to return
rcode = p.wait()

t.cancel()

プロセスが時間内に終了し、wait() が終了してコードがここで続行される場合、cancel() はタイマーを停止します。その間にタイマーが切れて別のスレッドで kill_proc を実行すると、wait() もここで続行され、cancel() は何もしません。rcode の値によって、タイムアウトしたかどうかがわかります。最も単純な kill_proc : (もちろん、そこで追加の処理を実行できます)

def kill_proc(self):
    os.kill(self.p, signal.SIGTERM)
于 2017-10-11T09:20:44.327 に答える