在Python中的同一进程中捕获stdout

时间:2010-04-16 17:04:49

标签: python stream

我有一个调用一堆函数的python脚本,每个函数都将输出写入stdout。有时当我运行它时,我想通过电子邮件发送输出(以及生成的文件)。我想知道如何捕获内存中的输出,以便我可以使用email模块来构建电子邮件。

到目前为止我的想法是:

  • 使用内存映射文件(但似乎我必须为此保留磁盘空间,我不知道输出会有多长)
  • 绕过所有这一切并将输出传递给sendmail(但如果我还想附加文件,这可能会很困难)

4 个答案:

答案 0 :(得分:13)

我修改了None的答案,使其成为一个上下文管理器:

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'

答案 1 :(得分:7)

捕获输出非常简单。

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()

答案 2 :(得分:3)

你说你的脚本“调用了很多函数”所以我假设它们是你的程序可以访问的python函数。我还假设您正在使用print在所有这些函数中生成输出。如果是这种情况,您只需将sys.stdout替换为StringIO.StringIO即可拦截您正在编写的所有内容。然后,您最终可以调用.getValue上的StringIO方法,以获取已发送到输出通道的所有内容。这也适用于使用写入sys.stdout

的子进程模块的外部程序

这是一种廉价的方式。我建议您使用logging模块进行输出。您可以更好地控制它的输出方式,您也可以更轻松地控制它。

答案 3 :(得分:1)

我修改了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()