Захват stdout в рамках одного процесса в Python
У меня есть python script, который вызывает кучу функций, каждый из которых записывает вывод в stdout. Иногда, когда я запускаю его, я хотел бы отправить результат в электронном письме (вместе с сгенерированным файлом). Я хотел бы знать, как я могу захватить вывод в памяти, поэтому я могу использовать модуль email
для создания электронной почты.
Мои идеи до сих пор были:
- используйте файл с отображением памяти (но мне кажется, что мне нужно зарезервировать место на диске для этого, и я не знаю, сколько будет времени на выходе)
- обойти все это и передать вывод на sendmail (но это может быть сложно, если я также хочу прикрепить файл)
Ответы
Ответ 1
Вы сказали, что ваш script "вызывает кучу функций", поэтому я предполагаю, что они являются функциями python, доступными из вашей программы. Я также предполагаю, что вы используете print
для генерации вывода во всех этих функциях. Если это так, вы можете просто заменить sys.stdout
на StringIO.StringIO
, который перехватит все, что вы пишете. Затем вы можете, наконец, вызвать метод .getValue
на своем StringIO
, чтобы получить все, что было отправлено на выходной канал. Это также будет работать для внешних программ, используя модуль подпроцесса, который записывается в sys.stdout
.
Это дешевый способ. Я бы рекомендовал, чтобы вы делали свой вывод с помощью модуля logging
. У вас будет гораздо больше контроля над тем, как он выводится, и вы также можете легко управлять им.
Ответ 2
Я изменил "Нет ответа", чтобы сделать его менеджером контекста:
import sys, StringIO, contextlib
class Data(object):
pass
@contextlib.contextmanager
def capture_stdout():
old = sys.stdout
capturer = StringIO.StringIO()
sys.stdout = capturer
data = Data()
yield data
sys.stdout = old
data.result = capturer.getvalue()
Использование:
with capture_stdout() as capture:
print 'Hello'
print 'Goodbye'
assert capture.result == 'Hello\nGoodbye\n'
Ответ 3
Это довольно просто для захвата вывода.
import sys, StringIO
old_stdout = sys.stdout
capturer = StringIO.StringIO()
sys.stdout = capturer
#call functions
print "Hi"
#end functions
sys.stdout = old_stdout
output = capturer.getvalue()
Ответ 4
И я модифицировал Gary Robinson, чтобы убедиться, что stdout
всегда восстанавливается, даже если есть исключение:
import sys, StringIO, contextlib
class Data(object):
pass
@contextlib.contextmanager
def capture_stdout():
old = sys.stdout
capturer = StringIO.StringIO()
data = Data()
try:
sys.stdout = capturer
yield data
finally:
sys.stdout = old
data.result = capturer.getvalue()