Вопрос-Ответ

Retrieving the output of subprocess.call() [duplicate]

Получение выходных данных subprocess.call()

Как я могу получить выходные данные процесса, запущенного с помощьюsubprocess.call()?

Передача StringIO.StringIO объекта в stdout выдает эту ошибку:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
return Popen(*popenargs, **kwargs).wait()
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 588, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 945, in _get_handles
c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
Переведено автоматически
Ответ 1

Если у вас Python версии 2.7 или новее, вы можете использовать subprocess.check_output который в основном делает именно то, что вы хотите (он возвращает стандартный вывод в виде строки).

Простой пример (версия Linux; см. Примечание):

import subprocess

print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])

Обратите внимание, что команда ping использует нотацию Linux (-c для count). Если вы попробуете это в Windows, не забудьте изменить это на -n для получения того же результата.

Как указано ниже, вы можете найти более подробное объяснение в этом другом ответе.

Ответ 2

Выходные данные из subprocess.call() должны перенаправляться только в файлы.

Вместо этого следует использовать subprocess.Popen(). Затем вы можете передать subprocess.PIPE для параметров stderr, stdout и / или stdin и считывать данные из каналов с помощью communicate() метода:

from subprocess import Popen, PIPE

p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode

Причина в том, что файлоподобный объект, используемый subprocess.call(), должен иметь реальный файловый дескриптор и, таким образом, реализовывать fileno() метод. Простое использование любого файлоподобного объекта не поможет.

Смотрите Здесь для получения дополнительной информации.

Ответ 3

Для Python 3.5 или более поздней версии рекомендуется использовать функцию run из модуля subprocess. Это возвращает CompletedProcess объект, из которого вы можете легко получить выходные данные, а также возвращаемый код.

from subprocess import PIPE, run

command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
Ответ 4

У меня есть следующее решение. Он фиксирует код выхода, стандартный вывод и stderr также выполняемой внешней команды:

import shlex
from subprocess import Popen, PIPE

def get_exitcode_stdout_stderr(cmd):
"""
Execute the external command and get its exitcode, stdout and stderr.
"""

args = shlex.split(cmd)

proc = Popen(args, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
exitcode = proc.returncode
#
return exitcode, out, err

cmd = "..." # arbitrary external command, e.g. "python mytest.py"
exitcode, out, err = get_exitcode_stdout_stderr(cmd)

У меня также есть запись в блоге об этом здесь.

Редактировать: решение было обновлено до более нового, которому не нужно записывать данные в temp. Файлы.

python subprocess