`subprocess.Popen`相比于`os.system()`多了很多可控制的参数,用起来更灵活。这里记录两段代码,一段是超时退出仿真,另一段代码是检测到Ctrl-C后自动结束所有的仿真进程。
subprocess.Popen
相比于os.system()
多了很多可控制的参数,用起来更灵活。这里记录两段代码,一段是超时退出仿真,另一段代码是检测到Ctrl-C后自动结束所有的仿真进程。
1. 仿真超时
遇到的坑:在shell=True时,p.kill()、p.terminate()会失效。看起来只是把shell进程给结束掉了,shell的子进程ncsim却还在。
经过大神的帮助和查阅stackoverflow相关帖子后,找到下面一个可行的方案。简单来说就是用process group
,把所有进程、子进程全总绑定到session_id。
使用时需要注意以下几点:
shell=True
preexec_fn=os.setsid
os.killpg(os.getpgid(p.pid), signal.SIGTERM)
代码如下:
def _run(cmd, stdout=None, timeout=600):
ret = "timeout"
p = subprocess.Popen(cmd,
stdout=stdout,
shell=True,
preexec_fn=os.setsid)
try:
t_start = time.time()
while True:
time.sleep(5)
if p.poll() is None:
dt = time.time() - t_start
if dt > timeout:
os.killpg(os.getpgid(p.pid), signal.SIGTERM)
ret = "timeout"
return ret
else:
ret = "done"
return ret
2. 检测Ctrl-C自动Kill所有子进程
其实方法就是上面的process group。在except KeyboardInterrupt
里发送signal.SIGTERM
就可以了。
except KeyboardInterrupt as e:
print(e)
os.killpg(os.getpgid(p.pid), signal.SIGTERM)
ret = "ctrl_c"
这个方法也适用于结束multiprocessing.pool
启动的子进程。
multiprocessing相关的内容可以参考这里:multiprocessing在并行仿真中的应用