2009-08-31 50 views
15

私はPythonで次のことを行う必要があります。私は、プロセス(サブプロセスモジュール?)を作成したいと思っています。そして、プロセスが正常に終了した場合、終了した時点から正確に続行する場合はPython:プロセスを実行し、1時間以内に終了しない場合は終了します。

  • です。
  • もしそうでなければ、プロセスは "スタックして" 1時間以内に終了しないで、それを強制終了して続行します(おそらくループで別の試行を与えます)。

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

答えて

20

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

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) 
8

(キルはところで、Pythonの2.6で新しく追加された)限り、あなたはプロセスの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 
>>> 
2

私も同様の質問があり、この回答が見つかりました。ドキュメントからの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 

あなたが産卵したかったので、ちょうど完全を期すために、私はどのように一定時間後にハングプロセスを終了させるもう一つの方法を追加したいですとにかく新しいプロセスですが、これはあなたの問題に対する最良の解決策ではないかもしれません。

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) 
関連する問題