且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在python中重定向函数的打印输出

更新时间:2023-12-04 10:43:52

对于 python3.4+,标准库中有一个上下文管理器.

with contextlib.redirect_stdout(file_like_object):...

这部分答案已更新,但主要针对仍然停留在 python2.x 世界中的人

如果您坚持使用旧版本的 python,那么自己编写这个上下文管理器并不难.关键是您可以将 sys.stdout 更新为您想要的任何类似文件的对象(这就是 print 写入的内容):

>>>导入系统>>>导入字符串IO>>>stdout = sys.stdout # 保留真实标准输出的句柄>>>sys.stdout = StringIO.StringIO() # 选择要写入的类文件对象>>>富()>>>sys.stdout = 标准输出>>>富()酒吧

创建一个上下文管理器来设置标准输出你想要什么时候进入上下文然后让上下文管理器在你 __exit__ 上下文时重置 stdout.

这是一个使用 contextlib 创建上下文管理器的简单示例:

导入上下文库导入系统@contextlib.contextmanagerdef stdout_redirect(其中):sys.stdout = 哪里尝试:产量在哪里最后:sys.stdout = sys.__stdout__定义 foo():打印酒吧"# StringIO 的例子导入字符串IO使用 stdout_redirect(StringIO.StringIO()) 作为 new_stdout:富()new_stdout.seek(0)打印来自 new_stdout 的数据:",new_stdout.read()new_stdout1 = StringIO.StringIO()使用 stdout_redirect(new_stdout1):富()new_stdout1.seek(0)打印来自 new_stdout1 的数据:",new_stdout1.read()# 现在有了一个文件对象:with open('new_stdout') as f:使用 stdout_redirect(f):富()# 只是为了证明我们确实按照我们应该的方式放回了标准输出打印现在在没有上下文的情况下调用 foo"富()

注意:

在 python3.x 上,StringIO.StringIO 已移至 io.StringIO.此外,在 python2.x 上,cStringIO.StringIO 的性能可能稍高一些.

Possible Duplicate:
Can I redirect the stdout in python into some sort of string buffer?

I have a function in python that prints something to the standard output

def foo():
    print("some text")

I want to 'redirect' the text that is being printed in this function into a variable, i.e. 'wrap' this function or whatever so that the text is stored in a variable:

text = wrapper(foo)

Is there a robust way to temporarily change sys.stdout or to open a variable as a FileObject, or something else?

For python3.4+, there's a context manager for this in the standard library.

with contextlib.redirect_stdout(file_like_object):
    ...


This part of the answer was updated, but is mostly for people who are still stuck in a python2.x world

If you're stuck on an older version of python, this context manager isn't too hard to write yourself. The key is that you can update sys.stdout to whatever file-like object you want (that's what print writes to):

>>> import sys
>>> import StringIO
>>> stdout = sys.stdout  # keep a handle on the real standard output
>>> sys.stdout = StringIO.StringIO() # Choose a file-like object to write to
>>> foo() 
>>> sys.stdout = stdout
>>> foo()
bar

To create a context manager to set stdout to whatever you want when you enter the context and then have the context manager reset stdout when you __exit__ the context.

Here's a simple example using contextlib to create the context manager:

import contextlib
import sys

@contextlib.contextmanager
def stdout_redirect(where):
    sys.stdout = where
    try:
        yield where
    finally:
        sys.stdout = sys.__stdout__

def foo():
    print 'bar'

# Examples with StringIO
import StringIO

with stdout_redirect(StringIO.StringIO()) as new_stdout:
    foo()

new_stdout.seek(0)
print "data from new_stdout:",new_stdout.read()

new_stdout1 = StringIO.StringIO()
with stdout_redirect(new_stdout1):
    foo()

new_stdout1.seek(0)
print "data from new_stdout1:",new_stdout1.read()

# Now with a file object:
with open('new_stdout') as f:
    with stdout_redirect(f):
        foo()

# Just to prove that we actually did put stdout back as we were supposed to
print "Now calling foo without context"
foo()

Note:

On python3.x, StringIO.StringIO has moved to io.StringIO. Also, on python2.x, cStringIO.StringIO might be slightly more performant.