Запуск команд оболочки и захват вывода
Я хочу написать функцию, которая будет выполнять команду в оболочке и возвращать ее вывод в виде строки, независимо от того, является ли это сообщением об ошибке или успешным выполнением. Мне нужно получить такой же результат, который я бы получил в командной строке.
Какой код мог бы это реализовать?
Например:
def run_command(cmd):
# ??????
print(run_command('mysqladmin create test -uroot -pmysqladmin12'))
# Ожидается вывод что-то вроде:
# mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'test'; database exists'
5 ответ(ов)
Это гораздо проще, но работает только в Unix (включая Cygwin) и Python 2.7:
import commands
print commands.getstatusoutput('wc -l file')
Этот код возвращает кортеж с (кодом_возврата, выводом).
Для решения, которое работает как в Python 2, так и в Python 3, используйте модуль subprocess
:
from subprocess import Popen, PIPE
output = Popen(["date"], stdout=PIPE)
response = output.communicate()
print(response)
В этом случае response
будет содержать вывод команды, а также код возврата.
В python3
для выполнения команд оболочки и получения их вывода можно использовать функцию subprocess.getoutput()
. Вот пример, который демонстрирует, как это сделать:
import subprocess
# Выполняем команду 'ls -l' и получаем ее вывод
output = subprocess.getoutput("ls -l")
print(output)
В этом коде мы импортируем модуль subprocess
, затем вызываем subprocess.getoutput()
с командой, которую хотим выполнить (в данном случае ls -l
), и сохраняем результат в переменной output
. После этого выводим результат на экран с помощью print()
. Это удобно, если нужно получить вывод команды как строку.
Вот пример функции, которая запускает дочерний процесс и выводит его вывод построчно в реальном времени, в том числе сообщения об ошибках. Если вы хотите, чтобы ошибки также отображались, вы можете перенаправить stderr в stdout, как показано ниже:
import subprocess
def runProcess(exe):
p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
# возвращает None, пока subprocess выполняется
retcode = p.poll()
line = p.stdout.readline()
yield line.decode('utf-8') # декодируем байты в строку
if retcode is not None:
break
Эта функция выдает строки по мере их поступления. Обычно для получения полного вывода процесса вам пришлось бы ждать его завершения, но в этом случае вы получаете каждую строку сразу.
Для вашего случая использование будет выглядеть так:
for line in runProcess('mysqladmin create test -uroot -pmysqladmin12'.split()):
print(line, end='') # используйте "end=''" для предотвращения добавления лишнего переноса строки
Таким образом, вы сможете видеть вывод команды mysqladmin
в реальном времени. Не забудьте обращаться с паролями и конфиденциальными данными осторожно!
Это хитрое, но очень простое решение, которое работает во многих ситуациях:
import os
os.system('sample_cmd > tmp')
print(open('tmp', 'r').read())
В данном коде создаётся временный файл (в данном случае называется tmp
), в который записывается вывод команды. Затем вы можете прочитать из него нужный вам результат.
Дополнительно из комментариев:
Если вы выполняете это задание однократно, вы можете удалить временный файл. Если же вам нужно делать это несколько раз, то нет необходимости удалять tmp
.
os.remove('tmp')
Вы можете использовать следующие команды для выполнения любой команды оболочки. Я использовал их на Ubuntu.
import os
os.popen('ваша команда здесь').read()
Примечание: Этот метод устарел с версии Python 2.6. Теперь вы должны использовать subprocess.Popen
. Ниже приведен пример:
import subprocess
p = subprocess.Popen("ваша команда", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print(p.decode('utf-8').split("\n"))
В этом примере стандартный вывод команды обрабатывается, и результат разделяется на строки. Не забудьте декодировать вывод, если вы работаете с Python 3.
Почему в первой строке Python-скрипта пишут "#!/usr/bin/env python"?
Сохранить график в файл изображения вместо его отображения
Преобразование списка словарей в DataFrame pandas
Как использовать десятичное значение шага в range()?
Как отсортировать список/кортеж списков/кортежей по элементу на заданном индексе