2010-10-27 82 views
6

我想使用子進程來運行程序,但我需要限制執行時間。例如,如果它運行超過2秒鐘,我想殺死它。如何在使用子進程時限制程序的執行時間?

對於常見的程序,kill()工作正常。但是,如果我嘗試運行/usr/bin/time something,kill()不能真正殺死程序。

但我的代碼似乎不太好,程序仍在運行。

import subprocess 
import time 

exec_proc = subprocess.Popen("/usr/bin/time -f \"%e\\n%M\" ./son > /dev/null", stdout = subprocess.PIPE, stderr = subprocess.STDOUT, shell = True) 

max_time = 1 
cur_time = 0.0 
return_code = 0 
while cur_time <= max_time: 
    if exec_proc.poll() != None: 
     return_code = exec_proc.poll() 
     break 
    time.sleep(0.1) 
    cur_time += 0.1 

if cur_time > max_time: 
    exec_proc.kill() 
+0

與http://stackoverflow.com/questions/1191374/subprocess-with-timeout – starrify 2013-10-12 11:48:43

回答

3

做到像這樣在你的命令行:

perl -e 'alarm shift @ARGV; exec @ARGV' <timeout> <your_command> 

這將運行命令<your_command><timeout>秒終止它。

虛設例如:

# set time out to 5, so that the command will be killed after 5 second 
command = ['perl', '-e', "'alarm shift @ARGV; exec @ARGV'", "5"] 

command += ["ping", "www.google.com"] 

exec_proc = subprocess.Popen(command) 

,或者您可以使用signal.alarm如果你想讓它使用python,但它是相同的()。

+6

應答用Perl Python的問題重複的,不錯... – 2010-10-27 13:50:53

+0

它運作良好,但是當我嘗試用「Perl -e「報警shift @ARGV; exec @ARGV'3/usr/bin/time ping google.com「,程序不會停止。 – 2010-10-27 14:29:22

+0

那麼如何處理/ usr/bin/time some_command? – 2010-10-27 14:30:05

9

如果您使用的是Python 2.6或更高版本,則可以使用multiprocessing模塊。

from multiprocessing import Process 

def f(): 
    # Stuff to run your process here 

p = Process(target=f) 
p.start() 
p.join(timeout) 
if p.is_alive(): 
    p.terminate() 

其實,多是此任務的錯誤的模塊,因爲它僅僅是一個控制一個線程運行多久方式。您無法控制該線程可能運行的任何子項。如奇點所示,使用signal.alarm是正常方法。

import signal 
import subprocess 

def handle_alarm(signum, frame): 
    # If the alarm is triggered, we're still in the exec_proc.communicate() 
    # call, so use exec_proc.kill() to end the process. 
    frame.f_locals['self'].kill() 

max_time = ... 
stdout = stderr = None 
signal.signal(signal.SIGALRM, handle_alarm) 
exec_proc = subprocess.Popen(['time', 'ping', '-c', '5', 'google.com'], 
          stdin=None, stdout=subprocess.PIPE, 
          stderr=subprocess.STDOUT) 
signal.alarm(max_time) 
try: 
    (stdout, stderr) = exec_proc.communicate() 
except IOError: 
    # process was killed due to exceeding the alarm 
finally: 
    signal.alarm(0) 
# do stuff with stdout/stderr if they're not None 
+0

謝謝,但它不起作用:< – 2010-10-27 14:35:03

+0

#嘗試一下。 3秒後,ping仍在運行。 進口子 導入時間 從多處理導入過程 DEF f()的: exec_proc = subprocess.Popen( 「/ USR /斌/時間平google.com」,殼=真) P =處理(目標= F) p.start() p.join(3) 如果p.is_alive(): p.terminate() time.sleep(10) – 2010-10-27 14:35:50

+0

你說得對。 'p.terminate()'只能殺死線程,而不會殺死任何生成的子進程。我不明白你爲什麼使用'shell = True',所以我會用一個解決方案來更新我的答案,使用signal.alarm作爲奇點建議。 – jamessan 2010-10-27 18:15:36

0

我使用os.kill(),但不知道它是否適用於所有操作系統。
僞代碼如下,並參見Doug Hellman的頁面。

proc = subprocess.Popen(['google-chrome'])            
os.kill(proc.pid, signal.SIGUSR1)</code>