如何从 Python 函数调用中捕获 stdout 输出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16571150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to capture stdout output from a Python function call?
提问by Nico Schl?mer
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,
并改变它。这样做时,它会将一些统计信息打印到标准输出,我想掌握这些信息。正确的解决方案是更改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()写入标准输出的任何内容。
How can I capture stdout output between two points in the code, e.g.,
如何捕获代码中两点之间的 stdout 输出,例如,
start_capturing()
do_something(my_object)
out = end_capturing()
?
?
采纳答案by kindall
Try this context manager:
试试这个上下文管理器:
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
Usage:
用法:
with Capturing() as output:
do_something(my_object)
outputis now a list containing the lines printed by the function call.
output现在是一个包含函数调用打印的行的列表。
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']
Update: They added redirect_stdout()to contextlibin Python 3.4 (along with redirect_stderr()). So you could use io.StringIOwith that to achieve a similar result (though Capturingbeing a list as well as a context manager is arguably more convenient).
更新:他们还说redirect_stdout()到contextlib在Python 3.4(沿redirect_stderr())。因此,您可以使用io.StringIO它来实现类似的结果(尽管Capturing作为列表和上下文管理器可以说更方便)。
回答by ForeverWintr
In python >= 3.4, contextlib contains a redirect_stdoutdecorator. 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.
This tool adds flexibility to existing functions or classes whose output is hardwired to 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:
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:
with open('help.txt', 'w') as f: with redirect_stdout(f): help(pow)To send the output of help() to 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.
This context manager is reentrant.
用于临时将 sys.stdout 重定向到另一个文件或类文件对象的上下文管理器。
此工具为输出硬连线到标准输出的现有函数或类增加了灵活性。
例如,help() 的输出通常发送到 sys.stdout。您可以通过将输出重定向到 io.StringIO 对象来捕获字符串中的输出:
f = io.StringIO() with redirect_stdout(f): help(pow) s = f.getvalue()要将 help() 的输出发送到磁盘上的文件,请将输出重定向到常规文件:
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 的全局副作用意味着此上下文管理器不适合在库代码和大多数线程应用程序中使用。它也对子流程的输出没有影响。但是,对于许多实用程序脚本来说,它仍然是一种有用的方法。
这个上下文管理器是可重入的。

