使用Python的subprocess.Popen时的异常处理

时间:2015-05-24 07:14:49

标签: python exception-handling subprocess

在处理打开文件时,Python具有with语法,可确保文件在离开块时关闭 - 无论异常等等。

with open('foo.txt') as f:
    foo = f.read()

由于进程也是资源,我想知道:使用Popen时是否可能或建议类似?例如,Popen.kill(); Popen.communicate()应该在finally条款中运行 - 假设我不介意阻止,直到流程结束?

3 个答案:

答案 0 :(得分:6)

从Python 3.2开始Popen是一个上下文管理器。

来自docs

  

通过with语句支持Popen对象作为上下文管理器:退出时,关闭标准文件描述符,等待进程。

这应该可以做你想要的。

这是来自标准库的subprocess.py的相关部分 在Python 3.4中:

def __enter__(self):
    return self

def __exit__(self, type, value, traceback):
    if self.stdout:
        self.stdout.close()
    if self.stderr:
        self.stderr.close()
    if self.stdin:
        self.stdin.close()
    # Wait for the process to terminate, to avoid zombies.
    self.wait()

现在你可以用Python 2.7做了

from subprocess import Popen

class MyPopen(Popen):

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        if self.stdout:
            self.stdout.close()
        if self.stderr:
            self.stderr.close()
        if self.stdin:
            self.stdin.close()
        # Wait for the process to terminate, to avoid zombies.
        self.wait()

if __name__ == '__main__':
    with MyPopen(['ls']) as p:
        print(p)

答案 1 :(得分:4)

对于2.7,您也可以使用@contextlib.contextmanager

import contextlib

@contextlib.contextmanager
def manage_process(process):
    try:
        yield process
    finally:
        for stream in [process.stdout, process.stdin, process.stderr]:
            if stream:
                stream.close()
        process.wait()

e.g:

with manage_process(Popen(['ls'])) as p:
    print(p)

答案 2 :(得分:2)

您可以向任何类添加两个自定义方法,以实现与with语句的兼容性。

class CustomObject(object):
    def __enter__(self):
        """ This method execudes when entering block. """
        return thing_you_want_to_use

    def __exit__(self, type, value, traceback):
        """ This method execudes on block exit. """
        # Tear things down.