【发布时间】:2009-11-27 17:47:10
【问题描述】:
我正在编写一些代码的单元测试,这些代码使用 sys.stderr.write 来报告输入错误。这是应该的,但这会破坏单元测试输出。有什么方法可以告诉 Python 不为单个命令输出错误消息,比如 2> /dev/null?
【问题讨论】:
标签: python unit-testing
我正在编写一些代码的单元测试,这些代码使用 sys.stderr.write 来报告输入错误。这是应该的,但这会破坏单元测试输出。有什么方法可以告诉 Python 不为单个命令输出错误消息,比如 2> /dev/null?
【问题讨论】:
标签: python unit-testing
我建议写一个上下文管理器:
import contextlib
import sys
@contextlib.contextmanager
def nostderr():
savestderr = sys.stderr
class Devnull(object):
def write(self, _): pass
def flush(self): pass
sys.stderr = Devnull()
try:
yield
finally:
sys.stderr = savestderr
现在,将您想要抑制其 stderr 的任何代码 sn-p 包装在 with nostderr(): 中,并且您拥有所需的本地化、临时、保证可逆的 stderr 抑制。
【讨论】:
__enter__ 和__exit__ 编写一个类当然不难,但是这样,对于足够简单的情况,您可以编写和阅读的样板代码更少;-)。
sys.stderr = os.devnull
您可以创建一个不对其输出执行任何操作的虚拟文件对象,并将 stderr 设置为:
class NullWriter:
def write(self, s):
pass
sys.stderr = NullWriter()
如果您只想让 stderr 安静一段时间,您可以使用 with 语句,如下所示:
class Quieter:
def __enter__(self):
self.old_stderr = sys.stderr
sys.stderr = NullWriter()
def __exit__(self, type, value, traceback):
sys.stderr = self.old_stderr
with Quieter():
# Do stuff; stderr will be suppressed, and it will be restored
# when this block exits
需要 Python 2.6 或更高版本,或者您可以在 Python 2.5 中使用from __future__ import with_statement。
【讨论】:
另一种可能性(除了分配给sys.stderr)是构建您的代码以将错误写入提供的文件,但将该文件默认为sys.stderr。然后您可以在测试期间提供 DevNull 编写器。
如果您确实想重新分配 sys.stderr,可以使用 unittest 框架为您管理它:
class DevNull(object):
def write(self, data):
pass
class MyTestCase(unittest.TestCase):
def setUp(self):
self.old_stderr = sys.stderr
sys.stderr = DevNull()
def tearDown(self):
sys.stderr = self.old_stderr
这样,每个测试 dev-null 的标准错误,然后在测试结束时恢复它。
【讨论】:
class DevNull(object):
def write(self, data): pass
sys.stderr = DevNull()
要找到一个不太持久的解决方案,可以想出如下方法:
_stderr = None
def quiet():
global _stderr
if _stderr is None:
_stderr = sys.stderr
sys.stderr = DevNull()
def verbose():
global _stderr
if _stderr is not None:
sys.stderr = _stderr
_stderr = None
函数名可能会更好
【讨论】:
quiet(...)这样的命令?