Запуск команд оболочки и захват вывода
Я хочу написать функцию, которая будет выполнять команду в оболочке и возвращать ее вывод в виде строки, независимо от того, является ли это сообщением об ошибке или успешным выполнением. Мне нужно получить такой же результат, который я бы получил в командной строке.
Какой код мог бы это реализовать?
Например:
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"?
Запуск дочерних процессов от имени другого пользователя из долгосрочного Python-процесса
Как удалить пакеты, установленные с помощью easy_install в Python?
Преобразование строки даты JSON в datetime в Python
Создание и чтение временного файла