在子进程Popen和通信后关闭所有文件的正确方法

Mar*_*arc 4 python subprocess twisted

在运行python Twisted应用程序的Ubuntu Linux机器上,可怕的“打开的文件太多”存在一些问题。在程序的许多地方,我们都在使用子进程Popen,如下所示:

Popen('ifconfig ' + iface, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
output = process.stdout.read()
Run Code Online (Sandbox Code Playgroud)

而在其他地方,我们使用子流程进行通信:

process = subprocess.Popen(['/usr/bin/env', 'python', self._get_script_path(script_name)],
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       close_fds=True)
out, err = process.communicate(data)
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,为了关闭所有打开的文件描述符,我到底需要做什么?Python文档尚不清楚。从我收集的信息(可能是错误的)中,communication()和wait()的确会自行清除所有打开的fds。但是Popen呢?如果我不打电话给我交流或等待,我是否需要在调用Popen之后显式关闭stdin,stdout和stderr?

Eri*_*ikR 5

根据此子流程模块(链接)的来源,如果调用communicate,则无需关闭stdoutstderr管道。

否则我会尝试:

process.stdout.close()
process.stderr.close()
Run Code Online (Sandbox Code Playgroud)

使用完process对象后。

例如,当您.read()直接致电时:

output = process.stdout.read()
process.stdout.close()
Run Code Online (Sandbox Code Playgroud)

在上面的模块源代码中查找如何communicate()定义,您将看到它在读取每个管道后关闭了每个管道,因此您也应该这样做。

  • 几乎在所有情况下,您都应该避免调用“process.stdout.read()”。如果 stdin 缓冲区为空或 stderr 缓冲区已满,而父进程仍在尝试从 stdout 读取数据,则可能会导致死锁。 (2认同)
  • 您是否考虑过使用`reactor.spawnProcess`?这可能会以多种方式使您的软件受益。 (2认同)