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

  • Можно ли захватить вывод интерпретатора Python из Python script?
  • Можно ли записать вывод CMD Windows из Python script?

Если да, то в каком либраре (y | ies) я должен смотреть?

Ответы

Ответ 1

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

python script_a.py | python script_b.py

Это связывает стандартный поток вывода script a со стандартным потоком ввода script 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. Вы также можете взглянуть на модуль pipes.

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

Ответ 2

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

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

Ответ "да", и лично мне нравится следующее, снятое с примеров в PEP 343 - "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"

Хорошим аспектом этого является то, что он может применяться выборочно только на части выполнения script, а не на всей его протяженности, и остается в силе даже тогда, когда необработанные исключения возникают в его контексте. Если вы повторно откроете файл в режиме добавления после его первого использования, вы можете скопировать результаты в один файл:

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

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

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

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

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

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

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

Ответ 4

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

Ответ 5

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

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

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

somescript.py | your-capture-program-here

и прочитать результат, просто прочитав стандартный ввод.

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