Как захватить выходные данные интерпретатора Python и/или CMD.EXE из сценария Python?
Вопрос
- Можно ли захватить вывод интерпретатора Python из сценария Python?
- Можно ли захватить выходные данные Windows CMD из сценария Python?
Если да, то какую библиотеку(y|ies) мне следует изучить?
Решение
Если вы говорите об интерпретаторе Python или CMD.exe, который является «родителем» вашего скрипта, то нет, это невозможно.В каждой POSIX-подобной системе (кажется, теперь вы используете Windows, и здесь может быть какая-то странность, о которой я не знаю, YMMV) каждый процесс имеет три потока: стандартный ввод, стандартный вывод и стандартную ошибку.Но по умолчанию (при работе в консоли) они направляются на консоль, но перенаправление возможно с использованием обозначения канала:
python script_a.py | python script_b.py
Это связывает стандартный поток вывода сценария А со стандартным потоком ввода сценария Б.В этом примере стандартная ошибка по-прежнему выводится на консоль.Смотрите статью о стандартные потоки в Википедии.
Если вы говорите о дочернем процессе, вы можете запустить его из Python следующим образом (stdin также является вариантом, если вам нужна двусторонняя связь):
import subprocess
# Of course you can open things other than python here :)
process = subprocess.Popen(["python", "main.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
x = process.stderr.readline()
y = process.stdout.readline()
process.wait()
См. Питон подпроцесс модуль для получения информации по управлению процессом.Для связи каналыprocess.stdin иprocess.stdout считаются стандартными. файловые объекты.
Для использования с каналами, чтение со стандартного ввода как Ласевк предложил сделать что-то вроде этого:
import sys
x = sys.stderr.readline()
y = sys.stdin.readline()
sys.stdin и sys.stdout — это стандартные файловые объекты, как отмечалось выше, определенные в система модуль.Возможно, вы также захотите взглянуть на трубы модуль.
Однако чтение данных с помощью readline(), как в моем примере, является довольно наивным способом получения данных.Если вывод не является линейным или недетерминированным, вы, вероятно, захотите изучить опрос который, к сожалению, не работает в Windows, но я уверен, что есть альтернатива.
Другие советы
Думаю, я могу указать вам хороший ответ на первую часть вашего вопроса.
1.Можно ли захватить вывод Python Interpreter из сценария Python?
Ответ "да", и лично мне нравится следующее, взятое из примеров в PEP 343 – Заявление "с" документ.
from contextlib import contextmanager
import sys
@contextmanager
def stdout_redirected(new_stdout):
saved_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout.close()
sys.stdout = saved_stdout
И используется так:
with stdout_redirected(open("filename.txt", "w")):
print "Hello world"
Приятным аспектом является то, что его можно применять выборочно только к части выполнения сценария, а не ко всему его объему, и он остается в силе, даже когда в его контексте возникают необработанные исключения.Если вы повторно откроете файл в режиме добавления после его первого использования, вы сможете собрать результаты в один файл:
with stdout_redirected(open("filename.txt", "w")):
print "Hello world"
print "screen only output again"
with stdout_redirected(open("filename.txt", "a")):
print "Hello world2"
Конечно, вышеизложенное также можно расширить, чтобы перенаправить sys.stderr
в тот же или другой файл.Также посмотрите это отвечать на соответствующий вопрос.
На самом деле, вы определенно можете, и это красиво, некрасиво и безумно одновременно!
Вы можете заменить sys.stdout и sys.stderr объектами StringIO, которые собирают выходные данные.
Вот пример: сохраните его как evil.py:
import sys
import StringIO
s = StringIO.StringIO()
sys.stdout = s
print "hey, this isn't going to stdout at all!"
print "where is it ?"
sys.stderr.write('It actually went to a StringIO object, I will show you now:\n')
sys.stderr.write(s.getvalue())
Запустив эту программу, вы увидите, что:
- ничего не пошло на стандартный вывод (куда обычно печатается print)
- первая строка, которая записывается в stderr, начинается с «It»
- следующие две строки — это те, которые были собраны в объекте StringIO.
Такая замена sys.stdout/err — это применение так называемого «monkeypatching».Мнения могут различаться, независимо от того, «поддерживается» это или нет, и это определенно уродливый хак, но он спас меня, когда я пытался обернуть внешние вещи один или два раза.
Проверено на Linux, а не на Windows, но должно работать так же хорошо.Дайте мне знать, если это работает в Windows!
Вы хотите подпроцесс.Посмотрите конкретно Popen в 17.1.1 и общайтесь в 17.1.2.
В каком контексте вы спрашиваете?
Вы пытаетесь записать вывод программы, которую запускаете из командной строки?
если да, то вот как это выполнить:
somescript.py | your-capture-program-here
и чтобы прочитать вывод, просто прочитайте со стандартного ввода.
Если, с другой стороны, вы выполняете этот сценарий или cmd.exe или что-то подобное из своей программы и хотите дождаться завершения сценария/программы и записать весь ее вывод, тогда вам нужно посмотреть библиотеку вызовы, которые вы используете для запуска этой внешней программы, скорее всего, есть способ попросить ее дать вам возможность прочитать выходные данные и дождаться завершения.