Нужен лучший способ выполнения команд консоли из python и регистрации результатов
У меня есть скрипт python, который должен выполнять несколько утилит командной строки. Вывод stdout иногда используется для дальнейшей обработки. Во всех случаях я хочу регистрировать результаты и возбуждать исключение, если обнаружена ошибка. Для достижения этой цели я использую следующую функцию:
def execute(cmd, logsink): logsink.log("executing: %s\n" % cmd) popen_obj = subprocess.Popen(\ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = popen_obj.communicate() returncode = popen_obj.returncode if (returncode <> 0): logsink.log(" RETURN CODE: %s\n" % str(returncode)) if (len(stdout.strip()) > 0): logsink.log(" STDOUT:\n%s\n" % stdout) if (len(stderr.strip()) > 0): logsink.log(" STDERR:\n%s\n" % stderr) if (returncode <> 0): raise Exception, "execute failed with error output:\n%s" % stderr return stdout
«logsink» может быть любым объектом python с методом журнала. Обычно я использую это для пересылки данных ведения журнала в конкретный файл или эха на консоль, или и того, и другого, или что-то еще …
Это работает довольно хорошо, за исключением трех проблем, когда мне нужен более мелкозернистый контроль, чем метод communication () обеспечивает:
- Вывод stdout и stderr может чередоваться на консоли, но вышеуказанная функция записывает их отдельно. Это может усложнить интерпретацию журнала. Как записывать строки stdout и stderr с чередованием в том же порядке, в каком они были выведены?
- Вышеуказанная функция будет только регистрировать выход команды после завершения команды. Это усложняет диагностику проблем, когда команды застревают в бесконечном цикле или занимают очень много времени по какой-то другой причине. Как получить журнал в режиме реального времени, пока команда все еще выполняется?
- Если журналы велики, может быть сложно интерпретировать, какая команда сгенерирована. Есть ли способ префикс каждой строки чем-то (например, первое слово строки cmd, за которым следует :).
- Получение вывода команды скрытой консоли?
- запустить скрипт python из командной строки, а затем ввести интерактивный режим
- Как запустить ipython из оболочки, запустив «python …»?
- Выполнять удаленные команды как root с помощью Python и paramiko
- Выполнение команд командной строки в PyCharm
Вы можете перенаправить файл, если хотите получить результат в файле для последующей оценки.
Вы уже определяете stdout / stderr процессов, которые вы выполняете с помощью методов stdout = / stderr =.
В вашем примере кода вы просто перенаправляете на скрипты current out / err assigments.
subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
sys.stdout и sys.stderr – это только файлы-подобные объекты. Как упоминается документация документации по sys.stdout , «Любой объект допустим, если он имеет метод write (), который принимает строковый аргумент».
f = open('cmd_fileoutput.txt', 'w') subprocess.Popen(cmd, shell=True, stdout=f, stderr=f)
Таким образом, вам нужно только дать ему класс с методом записи, чтобы перенаправить вывод.
Если вы хотите, чтобы и вывод консоли, и выход файла, могли создавать класс для управления выходом.
Общее перенаправление:
# Redirecting stdout and stderr to a file f = open('log.txt', 'w') sys.stdout = f sys.stderr = f
Создание класса перенаправления:
# redirecting to both class OutputManager: def __init__(self, filename, console): self.f = open(filename, 'w') self.con = console def write(self, data): self.con.write(data) self.f.write(data) new_stdout = OutputManager("log.txt", sys.stdout)
Перемежение зависит от буферизации, поэтому вы можете или не можете получить ожидаемый результат. (Возможно, вы можете отключить или уменьшить используемую буферизацию, но я не помню, как на данный момент)
Вы можете посмотреть pexpect ( http://www.noah.org/wiki/Pexpect )
Он решает 1) и 2) из коробки, префикс вывода может быть немного сложнее.
Еще один вариант:
def run_test(test_cmd): with tempfile.TemporaryFile() as cmd_out: proc = subprocess.Popen(test_cmd, stdout=cmd_out, stderr=cmd_out) proc.wait() cmd_out.seek(0) output = "".join(cmd_out.readlines()) return (proc.returncode, output)
Это будет чередовать stdout
и stderr
по желанию, в реальном файле, который вам удобно открыть.
Это отнюдь не полный или исчерпывающий ответ, но, возможно, вам следует изучить модуль Fabric.
http://docs.fabfile.org/0.9.1/
Делает параллельное выполнение команд оболочки и обработку ошибок довольно легко.
- Возвратный кортеж индекса и значение .max ()?
- Как объединить каждый элемент из двух списков в Python?
- Есть ли библиотека Python, которая облегчает создание утилит CLI, таких как команды управления Django?
- Отсутствует аргумент argpse в python 3
- Сценарий Python выводит вывод os.system перед печатью
- sys.argv не принимает предоставленный аргумент в python 3
- Как скомпилировать проект Visual Studio из командной строки?
- Передайте строку в командную строку
- Как создать функцию «cmd» в Python?
- Есть ли более pythonic способ открыть файл, если он указан как аргумент или stdin, если нет?
- Как получить доступ к аргументам командной строки в Python?