Python断言——改进失败的内省?

16 投票
7 回答
10570 浏览
提问于 2025-04-15 13:45

这个错误提示其实没什么用,它没有告诉我们涉及的表达式的具体值(假设常量实际上是变量名):

$ python -c "assert 6-(3*2)"
[...]
AssertionError

有没有更好用的 assert 实现方式呢?希望它能更花哨一点,但在执行时不能增加额外的负担(除了在 assert 失败的时候)……而且在使用 -O 标志时要关闭它。

编辑:我知道 assert 的第二个参数可以是一个字符串。我不想写这个……因为这个信息已经包含在被断言的表达式中了。遵循 DRY 原则(不要重复自己)。

7 个回答

7

正如 @Mark Rushakoff 所说,nose 可以评估失败的断言。它也适用于标准的 assert

# test_error_reporting.py
def test():
    a,b,c = 6, 2, 3
    assert a - b*c

nosetests 的帮助信息:

$ nosetests --help|grep -B2 assert
  -d, --detailed-errors, --failure-detail
                        Add detail to error output by attempting to evaluate
                        failed asserts [NOSE_DETAILED_ERRORS]

示例:

$ nosetests -d
F
======================================================================
FAIL: test_error_reporting.test
----------------------------------------------------------------------
Traceback (most recent call last):
  File "..snip../site-packages/nose/case.py", line 183, in runTest
    self.test(*self.arg)
  File "..snip../test_error_reporting.py", line 3, in test
    assert a - b*c
AssertionError:
    6,2,3 = 6, 2, 3
>>  assert 6 - 2*3


----------------------------------------------------------------------
Ran 1 test in 0.089s

FAILED (failures=1)
7

你可以给一个 assert 语句加上一条信息:

assert 6-(3*2), "always fails"

这条信息也可以动态生成:

assert x != 0, "x is not equal to zero (%d)" % x

想了解更多信息,可以查看 Python文档中的 assert 语句

11

把你的函数安装为 sys.excepthook -- 具体可以查看 官方文档。如果你的函数的第二个参数是 AssertionError,那么你可以深入检查各种信息;特别是通过第三个参数,也就是错误追踪信息,你可以找到出错的具体位置和代码行,获取导致错误的异常信息,还可以查看所有相关变量的值等等。模块 inspect 可以帮助你完成这些工作。

要做到这一点的全面性其实需要不少工作,但如果你在写 assert 的时候愿意接受一些限制,这个过程会简单很多(比如,只限制使用本地或全局变量,这样比起涉及闭包中的非本地变量来说,检查会容易得多,等等)。

撰写回答