我有一个带有perl worker子进程的长期运行的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()
答案 0 :(得分:6)
我认为这就是你所需要的:
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进程被杀之前,所有文件对象都将被关闭。
答案 1 :(得分:1)
快速实验表明,x = open("/etc/motd"); x = 1
会自行清理,不会留下任何打开的文件描述符。如果你将最后一个引用放到subprocess.Popen
,那么管道似乎就会留下来。是否有可能重新调用start_helper()
(或者甚至是其他Popen
)而没有明确地关闭和停止旧版本?