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

时间:2022-01-11 00:04:03

I'm using a Python library that does something to an object

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

do_something(my_object)

and changes it. While doing so, it prints some statistics to stdout, and I'd like to get a grip on this information. The proper solution would be to change do_something() to return the relevant information,

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

out = do_something(my_object)

but it will be a while before the devs of do_something() get to this issue. As a workaround, I thought about parsing whatever do_something() writes to stdout.

但是在do_something()的开发人员遇到这个问题之前还需要一段时间。作为一种解决方法,我考虑解析do_something()写入stdout的任何内容。

How can I capture stdout output between two points in the code, e.g.,

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

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

?

3 个解决方案

#1


122  

Try this context manager:

试试这个上下文管理器

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

Usage:

用法:

with Capturing() as output:
    do_something(my_object)

output is now a list containing the lines printed by the function call.

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

Advanced usage:

高级用法:

What may not be obvious is that this can be done more than once and the results concatenated:

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

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

Output:

输出:

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

#2


37  

In python >= 3.4, contextlib contains a redirect_stdout decorator. It can be used to answer your question like so:

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

From the docs:

来自文档:

Context manager for temporarily redirecting sys.stdout to another file or file-like object.

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

This tool adds flexibility to existing functions or classes whose output is hardwired to stdout.

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

For example, the output of help() normally is sent to sys.stdout. You can capture that output in a string by redirecting the output to an io.StringIO object:

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

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

To send the output of help() to a file on disk, redirect the output to a regular file:

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

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

To send the output of help() to sys.stderr:

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

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

Note that the global side effect on sys.stdout means that this context manager is not suitable for use in library code and most threaded applications. It also has no effect on the output of subprocesses. However, it is still a useful approach for many utility scripts.

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

This context manager is reentrant.

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

#3


-10  

Take a look at this link about reading and writing files in Python. It should give you a feel for how to write things to file in various ways.

看看这个关于在Python中读写文件的链接。它应该让您了解如何以各种方式写入文件。

#1


122  

Try this context manager:

试试这个上下文管理器

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

Usage:

用法:

with Capturing() as output:
    do_something(my_object)

output is now a list containing the lines printed by the function call.

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

Advanced usage:

高级用法:

What may not be obvious is that this can be done more than once and the results concatenated:

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

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

Output:

输出:

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

#2


37  

In python >= 3.4, contextlib contains a redirect_stdout decorator. It can be used to answer your question like so:

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

From the docs:

来自文档:

Context manager for temporarily redirecting sys.stdout to another file or file-like object.

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

This tool adds flexibility to existing functions or classes whose output is hardwired to stdout.

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

For example, the output of help() normally is sent to sys.stdout. You can capture that output in a string by redirecting the output to an io.StringIO object:

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

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

To send the output of help() to a file on disk, redirect the output to a regular file:

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

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

To send the output of help() to sys.stderr:

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

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

Note that the global side effect on sys.stdout means that this context manager is not suitable for use in library code and most threaded applications. It also has no effect on the output of subprocesses. However, it is still a useful approach for many utility scripts.

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

This context manager is reentrant.

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

#3


-10  

Take a look at this link about reading and writing files in Python. It should give you a feel for how to write things to file in various ways.

看看这个关于在Python中读写文件的链接。它应该让您了解如何以各种方式写入文件。