подпроцесс.проверка вывода (), похоже, не существует (Python 2.6.5)


Я читал документацию Python о модуле подпроцесса (см. здесь) и это говорит о subprocess.check_output() команда, которая, кажется, именно то, что мне нужно.

однако, когда я пытаюсь использовать его, я получаю ошибку, что он не существует, и когда я запускаю dir(subprocess) он не указан.

я запускаю Python 2.6.5, и код, который я использовал ниже:

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

кто-нибудь знает, почему это происходит?

3 74

3 ответа:

Он был введен в 2.7 см. docs.

использовать подпроцесс.К popen Если вы хотите на выходе:

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

Если он используется в значительной степени в коде, который вы хотите запустить, но этот код не должен поддерживаться в долгосрочной перспективе (или вам нужно быстрое исправление независимо от потенциальных головных болей обслуживания в будущем), тогда вы можете duck punch (aka monkey patch), где бы ни был импортирован подпроцесс...

просто поднимите код из 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) обновите свою версию, если хотите оставаться в безопасности. Кроме того, переопределение и определение внутренних функций самостоятельно-это худший кошмар следующего парня, особенно когда следующий парень-это вы несколько лет подряд, и вы забыли все о Хак-хаках grody, которые вы делали в прошлый раз! В целом: это очень редко хорошая идея.

благодаря предложению патча обезьяны (и мои попытки потерпели неудачу - но мы потребляли выход 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