14

Запуск команд оболочки и захват вывода

11

Я хочу написать функцию, которая будет выполнять команду в оболочке и возвращать ее вывод в виде строки, независимо от того, является ли это сообщением об ошибке или успешным выполнением. Мне нужно получить такой же результат, который я бы получил в командной строке.

Какой код мог бы это реализовать?

Например:

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 ответ(ов)

2

Это гораздо проще, но работает только в 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 будет содержать вывод команды, а также код возврата.

1

В python3 для выполнения команд оболочки и получения их вывода можно использовать функцию subprocess.getoutput(). Вот пример, который демонстрирует, как это сделать:

import subprocess

# Выполняем команду 'ls -l' и получаем ее вывод
output = subprocess.getoutput("ls -l")
print(output)

В этом коде мы импортируем модуль subprocess, затем вызываем subprocess.getoutput() с командой, которую хотим выполнить (в данном случае ls -l), и сохраняем результат в переменной output. После этого выводим результат на экран с помощью print(). Это удобно, если нужно получить вывод команды как строку.

1

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

0

Это хитрое, но очень простое решение, которое работает во многих ситуациях:

import os
os.system('sample_cmd > tmp')
print(open('tmp', 'r').read())

В данном коде создаётся временный файл (в данном случае называется tmp), в который записывается вывод команды. Затем вы можете прочитать из него нужный вам результат.

Дополнительно из комментариев: Если вы выполняете это задание однократно, вы можете удалить временный файл. Если же вам нужно делать это несколько раз, то нет необходимости удалять tmp.

os.remove('tmp')
0

Вы можете использовать следующие команды для выполнения любой команды оболочки. Я использовал их на 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.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь