【问题标题】:Sensible Way to Capture Stdout for Later Replay?捕获标准输出以供以后重播的明智方法?
【发布时间】:2011-09-09 19:16:59
【问题描述】:

作为尝试测试遗留函数的“打印到标准输出”副作用的一部分,我想捕获标准输出以供以后重播。我使用mock

目标(尽可能多地实现!)

  • stdout 仍会在正常情况下打印,但有一个额外的记录器
  • 理想情况下,这应该被“修补”或仅在上下文中出现

我的实现(如下)的补丁看起来有点重/粗。有没有更明智的方法来做到这一点? cStringIO?我可以使用mock 的任何更好的部分,而不是我的__getattr__ hack?

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

【问题讨论】:

  • 你为什么要定义__getattr__?将writeflush 调用传递给底层字符串就足够了。除此之外,代码对我来说看起来不错,除了我会使用 cStringIO 而不是附加到数组来保存输出。
  • __getattr__ 是这样所有其他方法调用将继续传递(刷新、关闭等)。使用数组主要是这样当我想查看捕获的数据时处理起来更简单。

标签: python stream mocking stdout


【解决方案1】:

你甚至不需要保存以前的标准输出 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

【讨论】:

  • 这种方法对我的应用程序有一些不理想的位:1)它假设没有其他人在此过程中替换 sys.stdout (在测试情况下这是不正确的)。 2) 输出不是 'tee'
【解决方案2】:

在这种情况下你不需要模拟:

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

print "stdout"

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

【讨论】:

  • mock 这里很适合补丁功能。我更想知道是否有任何 mock 构造函数会比我的 StreamCapturing 类更优雅。
猜你喜欢
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 2021-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多