Python的断言 - 改善失败的反省?(Python assert — improved intr

2019-07-02 16:35发布

这是一个相当无用的断言错误; 它并没有告诉参与表达式的值(假设使用常量实际上变量名):

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

有没有更好的assert在Python实现,是更看中? 它必须不会引入额外的开销超过执行(当断言失败除外)..并且如果必须关闭-O使用标志。

编辑 :我知道断言的第二个参数是一个字符串。 我不想写的..作为在正被断言表达编码。 DRY(不要重复自己)。

Answer 1:

安装的功能为您的sys.excepthook -看到的文档 。 你的函数,如果第二个参数是AssertionError ,可以反省你的心脏的内容; 特别是通过第三个参数,回溯,就可以得到在断言失败框架和确切位置,通过源或字节代码,所有相关变量的值等模块获取失败例外检查帮助。

在全一般性做起来相当一块工作,但取决于你愿意在你如何编写接受哪些约束assert的IT可以大大减轻(如限制他们只能局部或全局变量使得反省相比更容易一个封闭的非本地变量可以参与,等等)。



Answer 2:

您可以将消息发送给assert

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

该消息也可以动态建立:

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

见该assert语句 Python文档中获取更多信息。



Answer 3:

正如@马克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)


Answer 4:

鼻子的测试套件适用内省断言 。

然而,AFAICT,你要叫他们声称得到反省:

import nose
def test1():
    nose.tools.assert_equal(6, 5+2)

结果是

C:\temp\py>C:\Python26\Scripts\nosetests.exe -d test.py
F
======================================================================
FAIL: test.test1
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line
183, in runTest
    self.test(*self.arg)
  File "C:\temp\py\test.py", line 3, in test1
    nose.tools.assert_equal(6, 5+2)
AssertionError: 6 != 7
>>  raise self.failureException, \
          (None or '%r != %r' % (6, 7))

注意Asse田那里。 当我行只是assert 6 == 5+2 ,我会得到:

C:\temp\py>C:\Python26\Scripts\nosetests.exe -d test.py
F
======================================================================
FAIL: test.test1
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line
183, in runTest
    self.test(*self.arg)
  File "C:\temp\py\test.py", line 2, in test1
    assert 6 == 5 + 2
AssertionError:
>>  assert 6 == 5 + 2

另外,我不知道随便,如果他们声称的与被跳过-O ,但是这将是一个非常快速检查。



Answer 5:

添加消息到你的断言,如果断言失败,这将显示:

$ python -c "assert 6-(3*2), '6-(3*2)'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError: 6-(3*2)

我能想到的唯一办法自动提供这将是包含在过程调用的断言,然后检查堆栈获得该行的源代码。 额外的调用会,不幸的是,引进的开销进入测试并不会与被禁用-O



Answer 6:

这听起来像你真正想要做的是设置一个断点调试就在之前assert和喜爱的调试,就像你喜欢的检查。



Answer 7:

我编写了一个替代sys.excepthook (被称为任何未处理的异常),这是比标准更看中的一点。 它会分析其中出现异常的线和打印这是在这一行中提到的所有变量(不打印所有本地变量,因为这可能是噪音太大 - 还有,也许是重要的VAR是全球左右)。

我把它叫做py_better_exchook(完美的名字),它是在这里 。

示例文件:

a = 6

def test():
    unrelated_var = 43
    b,c = 2, 3
    assert a - b*c

import better_exchook
better_exchook.install()

test()

输出:

$ python test_error_reporting.py 
EXCEPTION
Traceback (most recent call last):
  File "test_error_reporting.py", line 12, in <module>
    line: test()
    locals:
      test = <local> <function test at 0x7fd91b1a05f0>
  File "test_error_reporting.py", line 7, in test
    line: assert a - b*c
    locals:
      a = <global> 6
      b = <local> 2
      c = <local> 3
AssertionError

还有一些其他的选择:

  • (这里介绍) https://github.com/albertz/py_better_exchook/
  • https://github.com/patrys/great-justice
  • 鼻子确实为断言失败类似的东西, 在这里看到 。
  • IPython中也有类似的东西( 这 )。 做到这一点: from IPython.core import ultratb; sys.excepthook = ultratb.VerboseTB() from IPython.core import ultratb; sys.excepthook = ultratb.VerboseTB()
  • 嘉平议的“cgitb.py”,这是Python的一部分, 在这里看到 , 这里的代码 。


文章来源: Python assert — improved introspection of failure?