进程终止后关闭 Python subprocess.PIPE

Close Python subprocess.PIPE after process is terminated

我正在使用 Python 2.7.8 在 Windows 环境中多次协调和自动化多个应用程序的 运行ning。在每个 运行 期间,我使用 subprocess.Popen 启动几个子进程,将 subprocess.PIPE 传递给 stdinstdout 如下:

proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

其中 cmd 是参数列表。

脚本等待外部触发器知道给定的 运行 何时完成,然后通过向 stdin 写入字符串来终止当前 运行ning 的每个应用程序每个 Popen 个对象。应用程序读取这个字符串,并执行它自己的正常关闭(这就是为什么我不简单地调用 kill()terminate())。

# Try to shutdown process
timeout = 5
try:
   if proc.poll() is None:
      proc.stdin.write(cmd)

      # Wait to see if proc shuts down gracefully
      while timeout > 0:
         if proc.poll() is not None:
            break
         else:
            time.sleep(1)
            timeout -= 1
      else:
         # Kill it the old fashioned way
         proc.kill()
except Error:
   pass   # Process as necessary...

应用程序完成后,我会得到一个 Popen 对象。如果我检查该对象的 stdinstdout 成员,我会得到如下内容:

<open file '<fdopen>', mode 'wb' at 0x0277C758>

脚本然后循环执行下一个 运行,重新启动必要的应用程序。

我的问题是,我是否需要每次都为 stdinstdout 文件描述符显式调用 close() 以避免泄漏,即在 finally 上面的语句?我想知道这是因为在给定脚本期间循环可能会出现数百次甚至数千次。

我查看了 subprocess.py 代码,但是管道的文件句柄是由 _subprocess 模块中明显的 Windows(-only) 调用创建的,所以我无法获得更多详细信息。

管道最终可能会在垃圾回收期间关闭,但您不应依赖它并显式关闭管道。

def kill_process(process):
    if process.poll() is None: # don't send the signal unless it seems it is necessary
        try:
            process.kill()
        except OSError: # ignore
            pass

# shutdown process in `timeout` seconds
t = Timer(timeout, kill_process, [proc])
t.start()
proc.communicate(cmd)
t.cancel()

.communicate() 方法关闭管道并等待子进程退出。