进程终止后关闭Python subprocess.PIPE

时间:2015-03-24 11:33:42

标签: python python-2.7 subprocess

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

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

其中cmd是参数列表。

脚本等待外部触发器知道给定运行何时完成,然后通过将字符串写入每个stdin对象的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>

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

我的问题是,我是否需要每次都为close()stdin文件描述符显式调用stdout,以避免泄漏,即finally声明如上?我想知道这一点,因为在给定的脚本中循环可能会发生数百甚至数千次。

我查看了subprocess.py代码,但管道的文件句柄是由_subprocess模块中明显的Windows(-only)调用创建的,所以我无法获得任何进一步的细节

1 个答案:

答案 0 :(得分:2)

管道最终可能会在垃圾收集过程中关闭,但您不应该依赖它并明确关闭管道。

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()方法关闭管道并等待子进程退出。