【问题标题】:Why do I get subprocess resource warnings despite the process being dead?尽管进程已死,为什么我会收到子进程资源警告?
【发布时间】:2019-07-29 19:51:28
【问题描述】:

我一直在试图弄清楚如何启动不同的子进程实例,然后杀死它们,然后创建新的。父 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。我只是复制了那个,因为我发布的答案/问题就是这样。我宁愿没有那个参数。


根据我试过的答案:

def kill(self):
    self.serapi.wait()
    #self.serapi.kill()
    self.serapi.terminate()
    #os.killpg(os.getpgid(self.serapi.pid), signal.SIGTERM)
    #self.serapi.wait()

以及上述的不同排列,但似乎没有任何效果。有什么建议吗?

【问题讨论】:

  • 您在子流程上是否wait()?即使在子进程退出后,它仍然是僵尸,直到其父进程调用wait() 并检索其退出状态。
  • @DanielPryden 我没有打电话给wait(),直到你提到它,我才知道电话的存在。
  • 太棒了!我想了很多,这就是我在下面写答案的原因。如果您觉得它有用,请随时点赞和/或接受它。很高兴我能帮上忙!
  • @DanielPryden 看着调用wait() 的码头,如果两者都是stdout,stderr = PIPE,似乎会陷入僵局,除了我的过程永远不会结束,直到我告诉它结束。

标签: python subprocess kill kill-process


【解决方案1】:

ResourceWarning: subprocess N is still running 警告来自subprocess.Popen 类的__del__ 方法。

如果您查看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?

【讨论】:

  • 我尝试了以下self.serapi.wait();#self.serapi.kill();#self.serapi.terminate(); 的不同变体,但没有奏效。所以我猜想调用wait() 然后终止/终止进程不起作用?还是我错过了什么?
  • 但是进程还在运行吗?我不明白发生了什么,因为当我执行ps 时,我看不到它...:/
  • 你应该先杀死进程,然后等待它。在内核级别,wait 的字面意思不是“等待”,而是“接收事后信息”。该进程实际上可能不是僵尸,这取决于您如何分叉它。但是Popen认为子进程必须仍在运行(或者必须是僵尸),因为您还没有收到任何事后信息。这有意义吗?
  • 好的,所以我在kill 之后打电话给wait(这个名字真的很糟糕)。我怎么知道一切是否成功?我确定我试过这个,但不清楚它是否有效。我想要做的是为我的每个单元测试运行一个新的子进程。我想创建一个新的子流程。
猜你喜欢
  • 2012-08-10
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多