我想
已经有很多关于这些事情的文章,但我觉得我还没有找到我正在寻找的优雅的pythonic解决方案。我也试图让对于完全不熟悉python的人保持相对可读(和简短)。
到目前为止我的方法(见下面的代码)是:
我试图避免定期轮询流程的解决方案,但我不确定原因。
有更好的方法吗?
import subprocess,multiprocessing,signal
import sys,os,time
def sigterm_handler(signal, frame):
print 'You killed me!'
for p in pids:
os.kill(p,9)
sys.exit(0)
def sigint_handler(signal, frame):
print 'You pressed Ctrl+C!'
sys.exit(0)
signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGTERM, sigterm_handler)
def f_wrapper(d):
print str(d) + " start"
p=subprocess.call(["sleep","100"])
pids.append(p.pid)
print str(d) + " done"
print "Starting to run things."
pids=[]
for i in range(5):
p=multiprocessing.Process(target=f_wrapper,args=(i,))
p.daemon=True
p.start()
print "Got things running ..."
while pids:
print "Still working ..."
time.sleep(1)
答案 0 :(得分:4)
一旦subprocess.call
返回,子流程就完成了 - call
的返回值是子流程的returncode
。因此,在列表pids
中累积这些返回码(btw不会在附加它的多进程和“主”进程之间同步)并向它们发送9
信号“好像”它们是进程ids而不是返回代码,绝对是错误的。
问题的另一个问题是绝对错误的是规范:
能够用'kill -9杀死它们 parent_process_pid”。
因为-9
表示父进程无法拦截信号(即明确指定-9
的目的) - 我想{{1}因此在这里是虚假的。
你应该使用-9
而不是threading
(每个“保姆”线程,或者进程,除了等待它的子进程之外什么都没做,那么为什么要在这么轻量级的任务上浪费进程呢? - );你还应该在主线程中调用multiprocessing
(以启动子进程并能够获取其suprocess.Process
以放入列表中)并将生成的进程对象传递给等待的保姆线程为它(当它完成报告并从列表中删除它)。子进程ID的列表应该由一个锁保护,因为主线程和几个保姆线程都可以访问它,并且一个集合可能是比列表更好的选择(更快的删除),因为你不关心顺序也不关于避免重复。
所以,大致(没有测试,所以可能有bug ;-)我会将你的代码更改为s / like:
.pid
答案 1 :(得分:2)
这段代码(下面的代码)似乎对我起作用,从命令行中“top”或ctrl-c查杀。 Alex的建议唯一真正的改变是用subprocess.Popen调用替换subprocess.Process(我不认为subprocess.Process存在)。
这里的代码也可以通过某种方式锁定标准输出来改进,这样就不会在进程之间打印重叠。
import subprocess, threading, signal
import sys, time
pobs = set() # set to hold the active-process objects
pobslock = threading.Lock() # a Lock object to make sure only one at a time can modify pobs
def numpobs():
with pobslock:
return len(pobs)
# signal handlers
def sigterm_handler(signal, frame):
print 'You killed me! I will take care of the children.'
with pobslock:
for p in pobs: p.kill()
sys.exit(0)
def sigint_handler(signal, frame):
print 'You pressed Ctrl+C! The children will be dealt with automatically.'
sys.exit(0)
signal.signal(signal.SIGINT, sigint_handler)
signal.signal(signal.SIGTERM, sigterm_handler)
# a function to watch processes
def p_watch(d, p):
print d, 'start', p.pid
rc = p.wait()
with pobslock:
pobs.remove(p)
print d, 'done, rc =', rc
# the main code
print "Starting to run things ..."
for i in range(5):
p = subprocess.Popen(['sleep', '4'])
with pobslock:
pobs.add(p)
# create and start a "daemon" to watch and report the process p.
t = threading.Thread(target=p_watch, args=(i, p))
t.daemon=True
t.start()
print "Got things running ..."
while numpobs():
print "Still working ..."
time.sleep(1)