如何在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

在Python2.7中是否有任何方法可以捕获并记录常规python脚本中的断言语句,不管断言是真是假 假设我在代码中断言以下行:

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