subprocess.check_output() doesn't seem to exist (Python 2.6.5)

前端 未结 3 873
逝去的感伤
逝去的感伤 2020-11-28 22:25

I\'ve been reading the Python documentation about the subprocess module (see here) and it talks about a subprocess.check_output() command which seems to be exac

相关标签:
3条回答
  • 2020-11-28 22:54

    It was introduced in 2.7 See the docs.

    Use subprocess.Popen if you want the output:

    >>> import subprocess
    >>> output = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE).communicate()[0]
    
    0 讨论(0)
  • 2020-11-28 23:01

    Thanks to the monkey patch suggestion (and my attempts failing - but we were consuming CalledProcessError output, so needed to monkey patch that)

    found a working 2.6 patch here: 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
    
    0 讨论(0)
  • 2020-11-28 23:04

    IF it's used heavily in the code you want to run but that code doesn't have to be maintained long-term (or you need a quick fix irrespective of potential maintenance headaches in the future) then you could duck punch (aka monkey patch) it in wherever subprocess is imported...

    Just lift the code from 2.7 and insert it thusly...

    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
    

    Minor fidgeting may be required.

    Do bear in mind though the onus is on you to maintain dirty little backports like this. If bugs are discovered and corrected in the latest python then you a) have to notice that and b) update your version if you want to stay secure. Also, overriding & defining internal functions yourself is the next guy's worst nightmare, especially when the next guy is YOU several years down the line and you've forgot all about the grody hacks you did last time! In summary: it's very rarely a good idea.

    0 讨论(0)
提交回复
热议问题