Подтвердить что ты не робот

Subprocess.check_output(), похоже, не существует (Python 2.6.5)

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

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

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

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

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

4b9b3361

Ответ 1

Он был введен в 2.7. Смотрите docs.

Используйте subprocess.Popen, если вы хотите:

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

Ответ 2

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

Просто снимите код с 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