以下玩具脚本说明了该问题:
#!/usr/bin/env python3
def bomb():
"""
>>> bomb()
Traceback (most recent call last):
File "<string>", line 18, in bomb
ZeroDivisionError: division by zero
<BLANKLINE>
During handling of the above exception, another exception occurred:
<BLANKLINE>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 20, in bomb
Exception: re-raised
"""
try:
1/0
except Exception as exception:
raise Exception('re-raised')
if __name__ == '__main__' and '__file__' in globals():
import sys
if len(sys.argv) > 1 and sys.argv[1] == '-t':
import doctest
doctest.testmod()
else:
bomb()
如果我在python解释器中执行bomb()
,则会得到由文档字符串指定的输出:
% python3
Python 3.5.1 (default, May 24 2016, 20:04:39)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exec(open('demo.py').read())
>>> bomb()
Traceback (most recent call last):
File "<string>", line 18, in bomb
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 20, in bomb
Exception: re-raised
>>>
doctest
,但是,错误地报告了失败:
**********************************************************************
File "./demo.py", line 5, in __main__.bomb
Failed example:
bomb()
Expected:
Traceback (most recent call last):
File "<string>", line 16, in bomb
ZeroDivisionError: division by zero
<BLANKLINE>
During handling of the above exception, another exception occurred:
<BLANKLINE>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 18, in bomb
Exception: re-raised
Got:
Traceback (most recent call last):
File "./demo.py", line 18, in bomb
1/0
ZeroDivisionError: division by zero
<BLANKLINE>
During handling of the above exception, another exception occurred:
<BLANKLINE>
Traceback (most recent call last):
File "/usr/lib/python3.5/doctest.py", line 1320, in __run
compileflags, 1), test.globs)
File "<doctest __main__.bomb[0]>", line 1, in <module>
bomb()
File "./demo.py", line 20, in bomb
答案 0 :(得分:0)
问题是doctest在内部如何工作。基本上,它会在同一python解释器中加载,编译和评估python的代码段。
这与python加载和执行给定代码段的方式不同。
这是做神奇的doctest片段:
# Don't blink! This is where the user's code gets run.
exec(compile(example.source, filename, "single",
compileflags, 1), test.globs)
当执行的代码引发异常时,回溯包含doctest引擎的堆栈框架的一部分,从而使其与您的期望有所不同。
traceback标头后面是可选的traceback堆栈,其堆栈 内容被doctest忽略。追溯堆栈通常是 省略,或从交互式会话中逐字复制。
现在,它的最后一部分似乎仅适用于单个例外; “多重或嵌套异常”不能那样工作,您可能无法检查其回溯。参见此thread。
如果您仍然要检查此内容,则可以使用另一个{doc}引擎,例如byexample。它具有compatibility mode with doctest,因此您无需重写所有内容。
免责声明:我是byexample的作者。正如我在thread中所解释的那样,我是doctest的忠实拥护者,但它有其局限性。我希望byexample可以填补空白并对其他人有用。