Получение выходных данных 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'
>>>
7 ответов
Выход из 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()
метод. Просто использование любого подобного файлу объекта не сработает.
Смотрите здесь для получения дополнительной информации.
Если у вас версия Python >= 2.7, вы можете использовать subprocess.check_output, который в основном делает именно то, что вы хотите (он возвращает стандартный вывод в виде строки).
Простой пример (версия для Linux, см. Примечание):
import subprocess
print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])
Обратите внимание, что команда ping использует нотацию linux (-c
для подсчета). Если вы попробуете это в Windows, не забудьте изменить его на -n
за тот же результат.
Как прокомментировано ниже, вы можете найти более подробное объяснение в этом другом ответе.
Для python 3.5+ рекомендуется использовать функцию запуска из модуля подпроцесса. Это возвращает 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)
У меня есть следующее решение. Он захватывает код завершения, стандартный вывод и стандартный вывод выполненной внешней команды:
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. файлы.
Недавно я только что понял, как это сделать, и вот несколько примеров кода из моего текущего проекта:
#Getting the random picture.
#First find all pictures:
import shlex, subprocess
cmd = 'find ../Pictures/ -regex ".*\(JPG\|NEF\|jpg\)" '
#cmd = raw_input("shell:")
args = shlex.split(cmd)
output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()
#Another way to get output
#output = subprocess.Popen(args,stdout = subprocess.PIPE).stdout
ber = raw_input("search complete, display results?")
print output
#... and on to the selection process ...
Теперь у вас есть выходные данные команды, хранящиеся в переменной "output". "stdout = subprocess.PIPE" говорит классу создать объект файла с именем "stdout" изнутри Popen. Насколько я могу судить, метод connect () действует просто как удобный способ возврата кортежа выходных данных и ошибок из процесса, который вы запустили. Кроме того, процесс запускается при создании экземпляра Popen.
Следующее захватывает stdout и stderr процесса в одной переменной. Это Python 2 и 3 совместимы:
from subprocess import check_output
command = ["ls", "-l"]
try:
output = check_output(command, stderr=STDOUT).decode()
success = True
except CalledProcessError as e:
output = e.output.decode()
success = False
Если ваша команда является строкой, а не массивом, добавьте к ней префикс:
import shlex
command = shlex.split(command)
В Ipython
ракушка:
In [8]: import subprocess
In [9]: s=subprocess.check_output(["echo", "Hello World!"])
In [10]: s
Out[10]: 'Hello World!\n'
На основании ответа Сарга. Отдайте саргу.