Как захватить вывод интерпретатора Python и / или CMD.EXE из скрипта Python?

  1. Можно ли захватить вывод интерпретатора Python из скрипта Python?
  2. Возможно ли захватить вывод Windows CMD из скрипта Python?

Если да, то к какому либрару следует обратиться?

24.08.2008 08:46:57
5 ОТВЕТОВ
РЕШЕНИЕ

Если вы говорите о интерпретаторе python или CMD.exe, который является «родителем» вашего скрипта, то нет, это невозможно. В каждой POSIX-подобной системе (кажется, что сейчас вы работаете с Windows, и это может иметь некоторую причуду, о которой я не знаю, YMMV), каждый процесс имеет три потока, стандартный ввод, стандартный вывод и стандартную ошибку. По умолчанию (при запуске в консоли) они направляются на консоль, но перенаправление возможно с использованием обозначения канала:

python script_a.py | python script_b.py

Это связывает стандартный поток вывода сценария a со стандартным потоком ввода сценария B. В этом примере стандартная ошибка по-прежнему поступает на консоль. Смотрите статью о стандартных потоках в Википедии.

Если вы говорите о дочернем процессе, вы можете запустить его из 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()

Обратитесь к модулю подпроцесса Python за информацией об управлении процессом. Для связи каналы process.stdin и process.stdout считаются стандартными файловыми объектами .

Для использования с каналами чтение из стандартного ввода, как lassevk предложил сделать что-то вроде этого:

import sys
x = sys.stderr.readline()
y = sys.stdin.readline()

sys.stdin и sys.stdout являются стандартными файловыми объектами, как отмечено выше, определенными в модуле sys . Вы также можете взглянуть на модуль трубы .

Чтение данных с помощью readline (), как в моем примере, является довольно наивным способом получения данных. Если выходные данные не являются линейно-ориентированными или недетерминированными, вы, вероятно, захотите изучить опрос, который, к сожалению, не работает в Windows, но я уверен, что есть какая-то альтернатива.

9
23.05.2017 11:45:43
Обратите внимание, что при вызове Python с использованием subprocess.Popen () часто бывает полезно передать флаг "-u", который отключает буферизацию в stdin / stdout / stderr. Python не выполняет автозапуск stdout, когда дочерний элемент начинает читать stdin, если вывод перенаправлен в канал, так что вы можете в конечном итоге заблокировать вечное чтение вывода, который буферизуется. Я столкнулся с этой проблемой, пытаясь обернуть / автоматизировать pdb.
D Coetzee 18.11.2011 16:29:49

В каком контексте вы спрашиваете?

Вы пытаетесь захватить вывод программы, которую вы запускаете из командной строки?

если так, то вот как это выполнить:

somescript.py | your-capture-program-here

и читать вывод, просто читать из стандартного ввода.

Если, с другой стороны, вы выполняете этот сценарий или cmd.exe или аналогичный файл из своей программы и хотите дождаться окончания работы сценария / программы и перехватить весь его вывод, вам нужно взглянуть на библиотеку. вызовы, которые вы используете для запуска этой внешней программы, скорее всего, есть способ попросить ее дать вам какой-нибудь способ прочитать вывод и дождаться завершения.

0
24.08.2008 09:05:20

Вы хотите подпроцесс . Посмотрите конкретно на Попена в 17.1.1 и пообщайтесь в 17.1.2.

1
24.08.2008 09:27:54

На самом деле, вы определенно можете, и это красиво, безобразно и безумно одновременно!

Вы можете заменить 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())

Когда вы запустите эту программу, вы увидите, что:

  • ничто не пошло в стандартный вывод (где печать обычно печатает в)
  • первая строка, которая записывается в stderr - это строка, начинающаяся с 'It'
  • следующие две строки - те, которые были собраны в объекте StringIO

Замена sys.stdout / err следующим образом - это приложение, которое называется monkeypatching. Мнения могут различаться, независимо от того, поддерживается ли это или нет, и это определенно уродливый хак, но он спас мой бекон при попытке обернуть внешний материал один или два раза.

Протестировано на Linux, а не на Windows, но должно работать так же хорошо. Дайте мне знать, если это работает на Windows!

3
29.04.2009 18:24:23

Я думаю, что могу указать вам хороший ответ на первую часть вашего вопроса.

1. Можно ли захватить вывод интерпретатора Python из скрипта 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в тот же или другой файл. Также см. Этот ответ на связанный вопрос.

5
23.05.2017 11:52:59