2008-08-24 2 views

ответ

9

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

python script_a.py | python script_b.py 

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

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

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

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

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

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

+1

Обратите внимание, что при вызове Python с использованием подпроцесса .Popen() часто бывает полезно передать флаг «-u», который отключает буферизацию на stdin/stdout/stderr. Python не запускает autoflush stdout, когда ребенок начинает читать stdin, если вывод перенаправлен на канал, так что вы можете в конечном итоге заблокировать вечный считываемый вывод, который буферизуется. Я столкнулся с этой проблемой, пытаясь обернуть/автоматизировать pdb. – 2011-11-18 16:29:49

0

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

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

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

somescript.py | your-capture-program-here 

и читать выход, только чтение со стандартного ввода.

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

1

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

3

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

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

4

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

1.     Можно ли захватить выход Python интерпретатора из сценария Python?

Ответ «да », и лично я, как следующие подняли из примеров, приведенных в документе PEP 343 -- The "with" Statement.

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