合理的方式捕获标准输出以便后续重放?

1 投票
2 回答
1330 浏览
提问于 2025-04-17 01:55

在测试一个旧函数的“打印到标准输出”的副作用时,我想捕捉标准输出,以便后续使用。我使用了 mock

我的目标(尽量实现更多的目标!)

  • 标准输出仍然可以正常打印,但同时有一个额外的记录器
  • 理想情况下,这个功能应该是“修补”的,或者只在特定的环境中发生

我下面的实现方式看起来有点复杂/不太好。有没有更简单的方法?比如 cStringIO?有没有更好的 mock 的用法可以替代我现在的 __getattr__ 的小技巧?

class StreamCapturing(object):
    def __init__(self, stream):
        self.captured = []
        self.stream = stream

    def __getattr__(self,attr):
        return getattr(self.stream,attr)

    def write(self, data):
        self.captured.append(data)
        self.stream.write(data)


import sys
import mock
with mock.patch('sys.stdout',StreamCapturing(sys.stdout)) as ctx:
    sys.stdout.write('a\n')
    print 'stdout'
    sys.__stdout__.write("the real one\n")
    print sys.stdout.captured
    sys.stdout.flush()

assert getattr(sys.stdout,'captured') is None

2 个回答

0

在这种情况下,你不需要使用模拟对象:

saved_stdout = sys.stdout
sys.stdout = StreamCapturing(saved_stdout)

print "stdout"

captured = "".join(sys.stdout.captured)
sys.stdout=saved_stdout
print "captured: ", captured
2

你甚至不需要自己保存之前的输出,Python会帮你处理这些。而且,记得使用cStringIO。

import sys
from cStringIO import StringIO

sys.stdout = captured = StringIO()
print "test string"
# test stuff
captured = captured.getvalue()
sys.stdout = sys.__stdout__
print "captured",captured

撰写回答