【问题标题】:How to clean up after subprocess.Popen?subprocess.Popen之后如何清理?
【发布时间】:2011-06-29 08:17:01
【问题描述】:

我有一个带有 perl 工作子进程的长时间运行的 python 脚本。数据通过其标准输入和标准输出传入和传出子进程。必须定期重新启动子进程。

不幸的是,运行一段时间后,文件用完了(“打开的文件太多”)。 lsof 显示了许多剩余的开放管道。

Popen 进程后清理的正确方法是什么?这是我现在正在做的事情:

def start_helper(self):
    # spawn perl helper
    cwd = os.path.dirname(__file__)
    if not cwd:
        cwd = '.'

    self.subp = subprocess.Popen(['perl', 'theperlthing.pl'], shell=False, cwd=cwd,
                                 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                                 bufsize=1, env=perl_env)

def restart_helper(self):
    # clean up
    if self.subp.stdin:
        self.subp.stdin.close()
    if self.subp.stdout:
        self.subp.stdout.close()
    if self.subp.stderr:
        self.subp.stderr.close()

    # kill
    try:
        self.subp.kill()
    except OSError:
        # can't kill a dead proc
        pass
    self.subp.wait() # ?

    self.start_helper()

【问题讨论】:

  • Popen.kill(或Popen.terminate)是您最好的选择。
  • 当你杀死它时,它是否会因为已经死亡以外的任何原因引发 OSError?
  • subprocess 中有一个无关紧要的错误,但它可以为_cleanup() bugs.python.org/issue1731717 提供一些启示
  • 如果您不在 Windows 上,请使用 close_fds=True(py3k 上的默认值)
  • 顺便说一句,在某些系统上,打开文件的数量限制非常小。

标签: python subprocess pipe popen lsof


【解决方案1】:

一个快速实验表明x = open("/etc/motd"); x = 1 会自行清理并且不留下任何打开的文件描述符。如果您放弃对subprocess.Popen 的最后一个引用,则管道似乎会粘在周围。您是否有可能在没有明确关闭和停止旧的情况下重新调用start_helper()(甚至是其他一些Popen)?

【讨论】:

    【解决方案2】:

    我认为这就是你所需要的:

    def restart_helper(self):
        # kill the process if open
        try:
            self.subp.kill()
        except OSError:
            # can't kill a dead proc
            pass
    
        self.start_helper()
        # the wait comes after you opened the process
        # if you want to know how the process ended you can add
        # > if self.subp.wait() != 0:
        # usually a process that exits with 0 had no errors
        self.subp.wait()
    

    据我所知,所有文件对象都将在 popen 进程被杀死之前关闭。

    【讨论】:

    • wait() 是不留下子进程和打开管道的关键。
    • 我认为这是真的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    相关资源
    最近更新 更多