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

StackOverflow https://stackoverflow.com/questions/24931

  •  09-06-2019
  •  | 
  •  

Вопрос

  1. Можно ли захватить вывод интерпретатора Python из сценария Python?
  2. Можно ли захватить выходные данные 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 или что-то подобное из своей программы и хотите дождаться завершения сценария/программы и записать весь ее вывод, тогда вам нужно посмотреть библиотеку вызовы, которые вы используете для запуска этой внешней программы, скорее всего, есть способ попросить ее дать вам возможность прочитать выходные данные и дождаться завершения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top