Как захватить вывод интерпретатора Python и / или CMD.EXE из скрипта Python? - PullRequest
8 голосов
/ 24 августа 2008
  1. Возможно ли захватить вывод интерпретатора Python из скрипта Python?
  2. Возможно ли захватить вывод Windows CMD из скрипта Python?

Если это так, в какой библиотеку (и |) мне следует обратиться?

Ответы [ 5 ]

9 голосов
/ 24 августа 2008

Если вы говорите о интерпретаторе 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 subprocess для получения информации об управлении процессом. Для связи каналы process.stdin и process.stdout считаются стандартными файловыми объектами .

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

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

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

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

5 голосов
/ 31 июля 2010

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

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

3 голосов
/ 27 августа 2008

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

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

1 голос
/ 24 августа 2008

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

0 голосов
/ 24 августа 2008

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

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

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

somescript.py | your-capture-program-here

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...