我想尽快重复执行子进程。但是,有时这个过程需要很长时间,所以我想杀掉它。 我使用signal.signal(...)如下所示:
ppid=pipeexe.pid
signal.signal(signal.SIGALRM, stop_handler)
signal.alarm(1)
.....
def stop_handler(signal, frame):
print 'Stop test'+testdir+'for time out'
if(pipeexe.poll()==None and hasattr(signal, "SIGKILL")):
os.kill(ppid, signal.SIGKILL)
return False
但有时这段代码会尝试阻止下一轮执行。 停止测试/ home / lu / workspace / 152 / treefit / test2超时 / bin / sh:/ home / lu / workspace / 153 / squib_driver:not found ---这是下一次执行;该程序错误地阻止了它。
有谁知道如何解决这个问题?我想及时停止不执行1秒钟.sleep(n)经常等待n秒。我不希望我希望它可以执行不到1秒
答案 0 :(得分:40)
你可以这样做:
import subprocess as sub
import threading
class RunCmd(threading.Thread):
def __init__(self, cmd, timeout):
threading.Thread.__init__(self)
self.cmd = cmd
self.timeout = timeout
def run(self):
self.p = sub.Popen(self.cmd)
self.p.wait()
def Run(self):
self.start()
self.join(self.timeout)
if self.is_alive():
self.p.terminate() #use self.p.kill() if process needs a kill -9
self.join()
RunCmd(["./someProg", "arg1"], 60).Run()
这个想法是你创建一个运行命令的线程,如果超时超过某个合适的值,则杀死它,在这种情况下为60秒。
答案 1 :(得分:2)
这是我作为子进程执行的监视程序编写的内容。我现在经常使用它,但我不是那么有经验,所以也许它有一些缺陷:
import subprocess
import time
def subprocess_execute(command, time_out=60):
"""executing the command with a watchdog"""
# launching the command
c = subprocess.Popen(command)
# now waiting for the command to complete
t = 0
while t < time_out and c.poll() is None:
time.sleep(1) # (comment 1)
t += 1
# there are two possibilities for the while to have stopped:
if c.poll() is None:
# in the case the process did not complete, we kill it
c.terminate()
# and fill the return code with some error value
returncode = -1 # (comment 2)
else:
# in the case the process completed normally
returncode = c.poll()
return returncode
用法:
return = subprocess_execute(['java', '-jar', 'some.jar'])
评论:
time.sleep()
值可以轻松更改为任何需要的内容。必须相应地记录time_out
; 文档:我对subprocess
模块的文档进行了一些努力,以了解subprocess.Popen
没有阻塞;这个过程是并行执行的(也许我这里没有使用正确的单词,但我认为这是可以理解的。)
但是正如我所写的那样,它的执行是线性的,我真的必须等待命令完成,并暂停一下,以避免命令中的错误暂停每晚执行脚本。
答案 2 :(得分:0)
我想这是面向事件的线程和进程编程中常见的同步问题。
如果您应始终只运行一个子进程,请确保在运行下一个子进程之前终止当前子进程。否则,信号处理程序可能会获得对最后一个子进程运行的引用,并忽略较旧的。
假设子进程A正在运行。在处理报警信号之前,启动子过程B.在此之后,您的警报信号处理程序会尝试终止子进程。由于当前PID(或当前子进程管道对象)在启动子进程时被设置为B,因此B被杀死并且A继续运行。
我的猜测是否正确?
为了让你的代码更容易理解,我会在杀死当前子进程的部分之后包含创建新子进程的部分。这表明在任何时候只有一个子进程在运行。信号处理程序可以执行子进程终止和启动,就好像它是循环中运行的迭代块一样,在这种情况下,事件驱动每1秒发出一次警报信号。
答案 3 :(得分:0)
以下是我使用的内容:
class KillerThread(threading.Thread):
def __init__(self, pid, timeout, event ):
threading.Thread.__init__(self)
self.pid = pid
self.timeout = timeout
self.event = event
self.setDaemon(True)
def run(self):
self.event.wait(self.timeout)
if not self.event.isSet() :
try:
os.kill( self.pid, signal.SIGKILL )
except OSError, e:
#This is raised if the process has already completed
pass
def runTimed(dt, dir, args, kwargs ):
event = threading.Event()
cwd = os.getcwd()
os.chdir(dir)
proc = subprocess.Popen(args, **kwargs )
os.chdir(cwd)
killer = KillerThread(proc.pid, dt, event)
killer.start()
(stdout, stderr) = proc.communicate()
event.set()
return (stdout,stderr, proc.returncode)
答案 4 :(得分:0)
有点复杂,我添加了answer to solve a similar problem:捕获标准输出,输入标准输入,并且能够在一段时间不活动后和/或在一些整体运行时间后终止。