8

可能重复:
我可以将 python 中的标准输出重定向到某种字符串缓冲区吗?

我在 python 中有一个函数,可以将某些内容打印到标准输出

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

我想将在这个函数中打印的文本“重定向”到一个变量中,即“包装”这个函数或其他任何东西,以便将文本存储在一个变量中:

text = wrapper(foo)

是否有一种可靠的方法来临时更改sys.stdout或将变量打开为 aFileObject或其他?

4

2 回答 2

21

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

with contextlib.redirect_stdout(file_like_object):
    ...

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

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

>>> 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

创建上下文管理器以在您进入上下文时将标准输出设置为您想要的任何内容,然后让上下文管理器在您进入上下文时重置标准输出__exit__

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

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

笔记:

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

于 2013-01-07T13:35:09.743 回答
7

在 Python 3.x 中,您只需重新定义print.

B = []

def print(str):
    global B
    B.append(str)

def A():
    print("example")

A()

>>> B
['example']

如果由于某种原因,您需要内置打印功能,只需执行以下操作:

from builtins import print
于 2013-01-07T13:36:28.397 回答