15

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

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

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

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()
4

2 回答 2

7

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

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 进程被杀死之前关闭。

于 2011-03-29T01:55:38.373 回答
1

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

于 2011-03-01T08:25:05.063 回答