【问题标题】:subprocess.check_output() doesn't seem to exist (Python 2.6.5)subprocess.check_output() 似乎不存在(Python 2.6.5)
【发布时间】:2011-06-16 10:39:15
【问题描述】:

我一直在阅读有关 subprocess 模块的 Python 文档(请参阅 here),其中谈到了 subprocess.check_output() 命令,这似乎正是我所需要的。

但是,当我尝试使用它时,我收到一个错误,指出它不存在,并且当我运行 dir(subprocess) 时它没有被列出。

我运行的是 Python 2.6.5,我使用的代码如下:

import subprocess
subprocess.check_output(["ls", "-l", "/dev/null"])

有人知道为什么会这样吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    它是在 2.7 中引入的,请参阅docs

    如果需要输出,请使用subprocess.Popen

    >>> import subprocess
    >>> output = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE).communicate()[0]
    

    【讨论】:

    • 与 check_output 不同,当进程返回非零返回码时,这不会引发 CalledProcessError
    • @SridharRatnakumar:当然因为它们之间有很大的区别,即:阻塞和非阻塞。它们适用于不同的用例!
    • 我把它塞进了一个lambda,像这样:check_output = lambda args: Popen(args, stdout = PIPE).communicate()[0]。仅仅因为我在一个交互式解释器中,并且在其中写出多行函数定义有点像 PITA。我在会议的早些时候使用了from subprocess import Popen, PIPE
    • 那怎么ping??我还能用 Popen 吗?
    【解决方案2】:

    如果它在您要运行的代码中大量使用,但该代码不必长期维护(或者您需要快速修复,而不管将来可能出现的维护问题)然后你可以在任何导入子流程的地方躲避拳(又名猴子补丁)......

    只需从 2.7 中提取代码并插入它...

    import subprocess
    
    if "check_output" not in dir( subprocess ): # duck punch it in!
        def f(*popenargs, **kwargs):
            if 'stdout' in kwargs:
                raise ValueError('stdout argument not allowed, it will be overridden.')
            process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
            output, unused_err = process.communicate()
            retcode = process.poll()
            if retcode:
                cmd = kwargs.get("args")
                if cmd is None:
                    cmd = popenargs[0]
                raise subprocess.CalledProcessError(retcode, cmd)
            return output
        subprocess.check_output = f
    

    可能需要轻微的坐立不安。

    请记住,尽管您有责任维护像这样肮脏的小后端。如果在最新的 python 中发现并纠正了错误,那么您 a) 必须注意这一点,并且 b) 如果您想保持安全,请更新您的版本。此外,自己覆盖和定义内部功能是下一个人最糟糕的噩梦,尤其是当下一个人是你几年后,你已经忘记了你上次所做的那些糟糕的黑客行为!总之:这很少是一个好主意。

    【讨论】:

    【解决方案3】:

    感谢猴子补丁建议(我的尝试失败了 - 但我们正在消耗 CalledProcessError 输出,因此需要对其进行猴子补丁)

    在这里找到了一个有效的 2.6 补丁: http://pydoc.net/Python/pep8radius/0.9.0/pep8radius.shell/

    """Note: We also monkey-patch subprocess for python 2.6 to
    give feature parity with later versions.
    """
    try:
        from subprocess import STDOUT, check_output, CalledProcessError
    except ImportError:  # pragma: no cover
        # python 2.6 doesn't include check_output
        # monkey patch it in!
        import subprocess
        STDOUT = subprocess.STDOUT
    
        def check_output(*popenargs, **kwargs):
            if 'stdout' in kwargs:  # pragma: no cover
                raise ValueError('stdout argument not allowed, '
                                 'it will be overridden.')
            process = subprocess.Popen(stdout=subprocess.PIPE,
                                       *popenargs, **kwargs)
            output, _ = process.communicate()
            retcode = process.poll()
            if retcode:
                cmd = kwargs.get("args")
                if cmd is None:
                    cmd = popenargs[0]
                raise subprocess.CalledProcessError(retcode, cmd,
                                                    output=output)
            return output
        subprocess.check_output = check_output
    
        # overwrite CalledProcessError due to `output`
        # keyword not being available (in 2.6)
        class CalledProcessError(Exception):
    
            def __init__(self, returncode, cmd, output=None):
                self.returncode = returncode
                self.cmd = cmd
                self.output = output
    
            def __str__(self):
                return "Command '%s' returned non-zero exit status %d" % (
                    self.cmd, self.returncode)
        subprocess.CalledProcessError = CalledProcessError
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-11
      • 2019-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多