我写了一个Python包,已经成功地使其与Python 2.7和Python 3.4完全兼容,但有一个例外一直困扰着我。该包包含一个命令行脚本,在我的单元测试中,我使用以下代码运行脚本的主要例程,同时覆盖sys.argv以传递argparse的命令行参数,并捕获脚本的stdout进行比较:
@contextlib.contextmanager
def runmain(mainfunction, arglist):
"""Run mainfunction with arglist in sys.srgv, and capture stdout."""
origargv, sys.argv = sys.argv, arglist
origout, sys.stdout = sys.stdout, io.StringIO()
rtn = mainfunction()
sys.stdout.seek(0)
yield (rtn, sys.stdout.read())
sys.stdout = origout
sys.argv = origargv
class test_imdutil_main(unittest.TestCase):
def test_help(self):
"""Test -h option."""
with runmain(imdutil_main, ['imdutil.py', '-h']) as (rtn, capture):
# do stuff with rtn and capture...
这段代码在Python 3.4中运行良好,但在Python 2.7中会产生一个错误:
TypeError: unicode argument expected, got 'str'
我还没有找到一种可在Python 2.7和Python 3.4之间通用的从任意函数中捕获标准输出(stdout)的方法。
顺便提一下,我必须承认,我不太理解装饰器(decorations),上下文管理器(context managers)或“yield”关键字。 我编写runmain()函数的灵感来自于:
http://schinckel.net/2013/04/15/capture-and-test-sys.stdout-sys.stderr-in-unittest.testcase/
顺便说一句,我的完整包来源于以下链接:
https://github.com/NF6X/pyImageDisk
目前,在Python 2.7下,由于这个问题,其单元测试部分损坏了。 有人能帮我想办法以便以便以一种便携、符合Python惯例的方式解决这个标准输出重定向问题吗?最好是不添加任何外部依赖项。
origout
并使用默认备份sys.__stdout__
,它也存在于两种 Python 中。 - Dimitris Fasarakis Hilliard