【问题标题】:How to limit program's execution time when using subprocess?使用子进程时如何限制程序的执行时间?
【发布时间】:2011-05-01 07:40:56
【问题描述】:

我想使用子进程来运行一个程序,我需要限制执行时间。例如,如果它运行超过 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()

【问题讨论】:

标签: python subprocess kill


【解决方案1】:

如果您使用的是 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

【讨论】:

  • # 试试看。 3 秒后,ping 仍在运行。 import subprocess import time from multiprocessing import Process def f(): exec_proc = subprocess.Popen("/usr/bin/time ping google.com", shell = True) p = Process(target=f) p.start() p .join(3) if p.is_alive(): p.terminate() time.sleep(10)
  • 你是对的。 p.terminate() 只会杀死线程,不会杀死任何产生的孩子。我不明白你为什么使用shell = True,所以我将使用signal.alarm 的解决方案来更新我的答案,就像奇点所暗示的那样。
【解决方案2】:

在你的命令行中这样做:

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

这将运行命令&lt;your_command&gt; 并在&lt;timeout&gt; 秒后终止它。

一个虚拟的例子:

# 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,但它是一样的。

【讨论】:

  • 用 Perl 回答一个 Python 问题,很好……
  • 它运行良好,但是当我尝试“perl -e 'alarm shift @ARGV; exec @ARGV' 3 /usr/bin/time ping google.com”时,程序不会停止。
  • 为什么不这样做:time perl -e 'alarm shift @ARGV; exec @ARGV' 3 ping google.com ???
  • @jleedev:什么??? perl, python, ruby​​, shell....编程语言只是一个工具,已经贴出来的答案也可以评论,因为它使用了shell!!!!!!
【解决方案3】:

我使用 os.kill() 但不确定它是否适用于所有操作系统。
伪代码如下,见Doug Hellman的页面。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 2012-03-27
    • 2018-11-05
    • 1970-01-01
    相关资源
    最近更新 更多