如何从Python函数调用捕获标准输出?

我正在使用一个Python库来对某个对象做些什么

do_something(my_object) 

并改变它。 在这样做的时候,它会打印一些统计信息到stdout,我想要掌握这些信息。 正确的解决办法是改变do_something()返回相关信息,

 out = do_something(my_object) 

但是do_something()的开发者会遇到这个问题。 作为一种解决方法,我想过parsing什么do_something()写入标准输出。

如何在代码中的两点之间捕获标准输出,例如,

 start_capturing() do_something(my_object) out = end_capturing() 

试试这个上下文pipe理器

 from cStringIO import StringIO import sys class Capturing(list): def __enter__(self): self._stdout = sys.stdout sys.stdout = self._stringio = StringIO() return self def __exit__(self, *args): self.extend(self._stringio.getvalue().splitlines()) del self._stringio # free up some memory sys.stdout = self._stdout 

用法:

 with Capturing() as output: do_something(my_object) 

output现在是一个包含由函数调用打印的行的列表。

高级用法:

可能不明显的是,这可以多次完成,并将结果连接起来:

 with Capturing() as output: print 'hello world' print 'displays on screen' with Capturing(output) as output: # note the constructor argument print 'hello world2' print 'done' print 'output:', output 

输出:

 displays on screen done output: ['hello world', 'hello world2'] 

在python> = 3.4中,contextlib包含一个redirect_stdout装饰器。 它可以用来回答你的问题,如下所示:

 import io from contextlib import redirect_stdout f = io.StringIO() with redirect_stdout(f): do_something(my_object) out = f.getvalue() 

从文档 :

上下文pipe理器用于临时将sys.stdoutredirect到另一个文件或类似文件的对象。

这个工具增加了现有的function或类输出硬连接到标准输出的灵活性。

例如,help()的输出通常发送到sys.stdout。 您可以通过将输出redirect到一个io.StringIO对象来捕获该输出:

  f = io.StringIO() with redirect_stdout(f): help(pow) s = f.getvalue() 

要将help()的输出发送到磁盘上的文件,请将输出redirect到一个常规文件:

  with open('help.txt', 'w') as f: with redirect_stdout(f): help(pow) 

要将help()的输出发送到sys.stderr:

 with redirect_stdout(sys.stderr): help(pow) 

请注意,sys.stdout的全局副作用意味着此上下文pipe理器不适合在库代码和大多数线程化的应用程序中使用。 它也不会影响子过程的输出。 但是,对于许多实用程序脚本来说,这仍然是一个有用的方法

这个上下文pipe理器是可重入的。

看看这个关于在Python中读写文件的链接。 它应该给你一个如何以各种方式写入文件的感觉。