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

79

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

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

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

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

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

robintw
источник

Ответы:

123

Он был представлен в 2.7 См. Документацию .

Используйте subprocess.Popen, если вам нужен вывод:

>>> import subprocess
>>> output = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE).communicate()[0]
user225312
источник
14
в отличие от check_output, это не срабатывает, CalledProcessErrorкогда процесс возвращает ненулевой код возврата.
Шридхар Ратнакумар,
1
@SridharRatnakumar: конечно, потому что между ними большая разница, а именно: блокирование и неблокирование. Они предназначены для разных случаев использования!
lpapp
Я толкнул его в lambdaтак: check_output = lambda args: Popen(args, stdout = PIPE).communicate()[0]. Просто потому, что я использую интерактивный интерпретатор, и это своего рода PITA, чтобы писать в них определения многострочных функций. Я использовал from subprocess import Popen, PIPEранее в сеансе.
ArtOfWarfare
как тогда пинг сделать ?? Могу ли я использовать Popen или?
TheCrazyProfessor
56

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

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

Роджер Хиткот
источник
2
Я согласен с этим методом. Я бы, наверное, указал местонахождение источника. Вы можете найти его на hg.python.org/cpython/file/d37f963394aa/Lib/subprocess.py#l544
Ehtesh Choudhury
1
Примечание. CalledProcessError не принимает вывод в python 2.6. (Я сразу укусил после использования этого хака! :()
Энди Хайден
cpython теперь находится на GitHub - check_outputдля Python 2.7 в настоящее время здесь: github.com/python/cpython/blob/2.7/Lib/subprocess.py#L194
jamesc
6

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