如何从Python函数调用中捕获stdout输出?

Nic*_*mer 93 python stdout capture

我正在使用一个对象做某事的Python库

do_something(my_object)
Run Code Online (Sandbox Code Playgroud)

并改变它.这样做时,它会向stdout打印一些统计信息,我想抓住这些信息.适当的解决方案是改变do_something()以返回相关信息,

out = do_something(my_object)
Run Code Online (Sandbox Code Playgroud)

但在开始讨论do_something()这个问题之前还需要一段时间.作为一种解决方法,我考虑解析do_something()对stdout的任何写入.

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

start_capturing()
do_something(my_object)
out = end_capturing()
Run Code Online (Sandbox Code Playgroud)

kin*_*all 158

试试这个上下文管理器

# import StringIO for Python 2 or 3
try:
    from StringIO import StringIO
except ImportError:
    from io 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
Run Code Online (Sandbox Code Playgroud)

用法:

with Capturing() as output:
    do_something(my_object)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

输出:

displays on screen                     
done                                   
output: ['hello world', 'hello world2']
Run Code Online (Sandbox Code Playgroud)

更新:他们还说redirect_stdout()contextlib在Python 3.4(沿redirect_stderr()).因此,您可以使用io.StringIO它来实现类似的结果(尽管Capturing列表以及上下文管理器可以说更方便).

  • 很好的回答,谢谢.对于Python 3,在上下文管理器中使用`from io import StringIO`而不是第一行. (23认同)

For*_*ntr 67

在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()
Run Code Online (Sandbox Code Playgroud)

来自文档:

用于临时将sys.stdout重定向到另一个文件或类文件对象的上下文管理器.

此工具为输出硬连线到stdout的现有函数或类增加了灵活性.

例如,help()的输出通常发送到sys.stdout.您可以通过将输出重定向到io.StringIO对象来捕获字符串中的输出:

  f = io.StringIO() 
  with redirect_stdout(f):
      help(pow) 
  s = f.getvalue()
Run Code Online (Sandbox Code Playgroud)

要将help()的输出发送到磁盘上的文件,请将输出重定向到常规文件:

 with open('help.txt', 'w') as f:
     with redirect_stdout(f):
         help(pow)
Run Code Online (Sandbox Code Playgroud)

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

with redirect_stdout(sys.stderr):
    help(pow)
Run Code Online (Sandbox Code Playgroud)

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

此上下文管理器是可重入的.