如何在python脚本中捕获断言
在Python2.7中是否有任何方法可以捕获并记录常规python脚本中的断言语句,不管断言是真是假 假设我在代码中断言以下行:如何在python脚本中捕获断言,python,python-2.7,assert,Python,Python 2.7,Assert,在Python2.7中是否有任何方法可以捕获并记录常规python脚本中的断言语句,不管断言是真是假 假设我在代码中断言以下行: assert len(lst) ==4 所以,任何方法都可以记录传递的语句,在哪一行,它是真的还是假的。我不想使用包装器函数,寻找python中内置的东西 注意:我想要实现的是,假设我的遗留代码有1000条assert语句,在不更改代码的情况下,我应该能够记录执行了哪个assert语句,输出是什么,这在python 2.7中是可以实现的 是的,您可以定义自定义exc
assert len(lst) ==4
所以,任何方法都可以记录传递的语句,在哪一行,它是真的还是假的。我不想使用包装器函数,寻找python中内置的东西
注意:我想要实现的是,假设我的遗留代码有1000条assert语句,在不更改代码的情况下,我应该能够记录执行了哪个assert语句,输出是什么,这在python 2.7中是可以实现的 是的,您可以定义自定义excepthook来记录一些额外信息:
import sys
import logging
def excepthook(*args):
logging.getLogger().error('Uncaught exception:', exc_info=args)
sys.excepthook = excepthook
assert 1==2
编辑:哎哟,我忘了你想写日志,即使它是真的:哦,好吧,我会留一会儿,以防它通知你或其他人…这是我能做到的,因为在Python2.7中似乎不可能做到。我创建了一个包装器函数
try:
assert len(lst) == 4
print "True"
except AssertionError as e:
print "False"
import inspect
def assertit(condition,message):
# The caller method
(frame, filename, line_number,function_name, lines, index) = inspect.getouterframes(inspect.currentframe())[1]
detailed_message=" => {message} [ {filename} : {line_number}]".format(message=message,line_number=line_number,
filename=filename)
if condition:
print "True %s"%detailed_message
return
raise AssertionError("False: %s"%detailed_message)
assertit(1==1,"Check if 1 equal 1")
assertit(1==2,"Check if 1 equal 2")
### HERE IS THE OUTPUT
True => Check if 1 equal 1 [ test_cases.py : 20]
Traceback (most recent call last):
File "test_cases.py", line 21, in <module>
assertit(1==2,"Check if 1 equal 2")
File "test_cases.py", line 19, in assertit
raise AssertionError("False: %s"%detailed_message)
AssertionError: False: => Check if 1 equal 2 [ test_cases.py : 21]
这是一个概念证明。所以请投反对票,否则我会删除它。。。 其思想是在执行时用print语句替换assert语句
import ast
import inspect
from your_module import main
def my_assert(test_result, msg):
assert test_result, msg
# if test_result is True, just print the msg
return "assert: {}, {}".format(test_result, msg)
class Transformer(ast.NodeTransformer):
def visit_Assert(self, node):
f = ast.Name(id='my_assert', ctx=ast.Load())
c = ast.Call(func=f, args=[node.test, node.msg], keywords=[])
p = ast.Print(values=[c], nl=True)
# set line#, column offset same as the original assert statement
f.lineno = c.lineno = p.lineno = node.lineno
f.col_offset =c.col_offset = p.col_offset = node.col_offset
return p
def replace_assert_with_print(func):
source = inspect.getsource(func)
ast_tree = ast.parse(source)
Transformer().visit(ast_tree)
return compile(ast_tree, filename="<ast>", mode="exec")
if __name__ == '__main__':
exec(replace_assert_with_print(main))
main(4)
抱歉-您是什么意思?您可以通过任何方式记录传递的语句?似乎你想记录某个东西而不是断言它。你想在异常时记录吗?不,我想知道这是否可能,在执行过程中,解释器看看它是否是一个断言语句,它应该告诉它执行了哪一行,是真是假。还有assert语句是什么。你可以用except关键字捕捉assert异常,就像捕捉其他异常一样。除了AssertionError@sudhanshu-似乎您要求断言的行为与非断言的行为类似。这就像是问是否有办法让口述像列表一样。。。我认为您可能能够实现这一点的唯一方法是注册一个导入钩子,将所有断言语句更改为适当的日志语句……虽然这似乎可以实现所请求的目标,我确实想知道它与if语句有什么不同,为什么要用assert开头?它与if没有区别,但是OP有asserts,所以我只是从我的头顶上展示了一个简单的例子,我清楚地提到了,先生,没有包装器。是python 2.7中的任何默认特性,以及记录条件的方式。一般来说,在本例中,assert lenlst==4它不是一个包装器,它是python中内置的捕获异常fwiw的功能,您可以优化assert语句,在这种情况下,无论发生什么情况,都可以打印True。另外,这不会显示行号等。谢谢,这很有帮助,但是的,我也在寻找一些如何捕捉if true以及如何记录语句和行的方法。我认为包装函数是最好的选择,但你说你不想这样。无论如何,我都会更新答案以包含一个例子,以防你改变主意:好吧,即使我使用包装器函数,你是否意识到,代码中的语句将给出真或假,而不是语句。对吗?@sudhanshu good catch,我没有运行那个。你可以做一些更复杂的事情,但在阅读你的笔记后,你根本不想更改assert语句,因为这是很多遗留代码,我没有一个好的解决方案。谢谢@rofls,我现在创建了包装函数,这是我所能做的最好的。检查我发布的答案。谢谢看一下我的解决方案,我们似乎也在做同样的事情,我还传递了一条消息,来自被调用方方法的模块和行号。哦……我想我可以用try-except包装assert语句,而不是用print替换statement@sundhanshu我试图满足要求:不更改代码:-是的,我理解,但我认为exec语句引起了一些问题mac上出现问题,出现错误弹出窗口“Python意外退出”。谢谢
def main(x):
assert x == 4, "hey {} is not 4".format(x)
return x