我一直试图弄清楚如何启动不同的子流程实例然后杀死它们然后创建新的子流程实例。父python进程永远不会,它只会杀死子进程。我在SO上跟踪了很多链接,但是一旦父python进程结束,我就会收到以下消息:
F/Users/Lucifer/miniconda3/envs/rltp/lib/python3.6/subprocess.py:761: ResourceWarning: subprocess 40909 is still running ResourceWarning, source=self)
这看起来很有趣,因为我做了ps
,但我什么都没得到:
PID TTY TIME CMD
7070 ttys001 0:00.06 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp Lucifer
7072 ttys001 0:00.61 -bash
17723 ttys002 0:00.06 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp Lucifer
17725 ttys002 0:00.06 -bash
38586 ttys002 0:00.16 sertop --no_init
我只是想开始一个过程:
self.serapi = subprocess.Popen(['sertop','--no_init'],
stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
preexec_fn=os.setsid,shell=True
,)
杀了它:
os.killpg(os.getpgid(self.serapi.pid), signal.SIGTERM)
上面的代码基本上是从顶部答案复制而来的:
How to terminate a python subprocess launched with shell=True
但我不确定为什么我收到这条消息。我成功地杀死了孩子的过程吗?我计划开始并杀死其中许多人。
注意我不知道或不需要shell=True
。我只是复制了那个cuz,这就是我发布的答案/问题。我宁愿没有那个参数。
根据我试过的答案:
def kill(self):
self.serapi.wait()
#self.serapi.kill()
self.serapi.terminate()
#os.killpg(os.getpgid(self.serapi.pid), signal.SIGTERM)
#self.serapi.wait()
以及上述的不同排列但似乎没有任何效果。有什么建议?
ResourceWarning: subprocess N is still running
警告来自__del__
类的subprocess.Popen
方法。
如果你看看source for that method,你会看到这个评论:
# Not reading subprocess exit status creates a zombie process which
# is only destroyed at the parent python process exit
_warn("subprocess %s is still running" % self.pid,
ResourceWarning, source=self)
解决方案是确保您在子进程上调用wait()
。
有关更多背景信息,请参阅NOTES section of the man page for wait(2)
。
在Python中,处理这种情况的最简单方法是跟踪你创建的所有Popen
对象,并确保直接或间接地在它们上调用wait()
。
或者,您可以安装忽略SIGCHLD
事件的SIGCHLD
处理程序;然后你的孩子进程会立即消失,但你现在无法在他们身上调用wait()
。另见How can I prevent zombie child processes?和How can I handle SIGCHLD?