为什么在进程已死的情况下仍会收到子进程资源警告?



我一直在试图弄清楚如何启动不同的子进程实例,然后杀死它们,然后创建新的子进程实例。父 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)

上面的代码基本上是从顶部答案复制而来的:

如何终止使用 shell=True 启动的 python 子进程

但我不确定为什么我会收到这条消息。我是否成功杀死了子进程?我计划开始并杀死他们中的许多人。


注意 我不知道或不需要shell=True。我只是复制了那个,这就是我发布的答案/问题的方式。我宁愿没有那个参数。


根据我尝试的答案:

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警告来自subprocess.Popen类的__del__方法。

如果您查看该方法的来源,您将看到以下评论:

# 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 部分以获取wait(2)

在 Python 中,处理这种情况的最简单方法是跟踪您创建的所有Popen对象,并确保某些内容直接或间接调用wait()它们。

或者,您可以安装一个忽略SIGCHLD事件的SIGCHLD处理程序;然后您的子进程将立即消失,但您现在将无法对它们调用wait()另请参阅如何防止僵尸子进程?以及我如何处理 SIGCHLD?

最新更新