2016-11-03 139 views
-1

是存在的,我們可以捕捉和記錄一般Python腳本的斷言語句,儘管斷言在Python2.7任何方式是真的還是假 假設在代碼中,我斷言下面一行:如何捕捉python腳本斷言

assert len(lst) ==4 

所以有什麼方法可以記錄什麼語句傳遞,在哪一行,它是真或假。我不想使用包裝函數,尋找python內置的東西。

注:我想要實現的是,假設我有遺留代碼有1000個斷言語句,而不更改代碼,我應該能夠記錄哪個斷言語句被執行以及輸出是什麼,是否可以實現python 2.7。

+0

對不起 - 你什麼意思「任何方式通過什麼語句可以登錄」?看起來你想要記錄某些東西而不是_assert_它。 – mgilson

+0

你想登錄異常嗎? –

+0

不,我想知道是否有可能,不知何故解釋器在執行過程中看到它是否有斷言聲明,它應該告訴它執行的是哪一行,是真還是假。還有什麼是斷言聲明。 – sudhanshu

回答

2

是的,你可以自定義一個excepthook記錄一些額外的信息:

import sys 
import logging 
def excepthook(*args): 
    logging.getLogger().error('Uncaught exception:', exc_info=args) 

sys.excepthook = excepthook 

assert 1==2 

編輯:哎呀我忘了你想登錄,即使這是真的:)哦,我會離開這個一點點如果它通知你或其他人...

+1

謝謝這是有幫助的,但是我也在尋找一些如何能夠捕獲到真實情況並記錄聲明和行。 – sudhanshu

+0

我認爲封裝函數是你最好的選擇,但是你說你不想要。無論如何,我會更新答案以包含示例,以防您改變主意:) – rofls

+1

好吧即使我使用包裝函數,您是否已經意識到,代碼中的語句會給出True或False,而不是語句.Right? – sudhanshu

2
try: 
    assert len(lst) == 4  
    print "True" 
except AssertionError as e: 
    print "False" 
+0

雖然這看起來是正確的完成要求的目標,我不知道它是如何不同於if語句(爲什麼使用斷言開始?) – rofls

+1

它與if沒有區別,但是OP聲明瞭,所以我只是展示了一個簡單的例子,從我的頭頂 – tinySandy

+0

我明確提到了Sir,No wrapper。 Python 2.7中的任何默認功能以及如何記錄條件。在這種情況下通用的方式「assert len(lst)== 4」 – sudhanshu

1

這是我可以實現closet,因爲似乎不可能在Python2.7。我創建了一個包裝函數。

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] 
0

這是一個概念驗證。所以請downvote,否則我會刪除它... 這個想法是在執行時用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) 

這裏是your_module.py

def main(x): 
    assert x == 4, "hey {} is not 4".format(x) 
    return x 
+0

謝謝看看我的解決方案,似乎我們正在做同樣的事情,我也傳遞一條消息,並從檢查獲取被調用方法的模塊和行號。 – sudhanshu

+0

哦....我想我可以用'try-except'包裝'assert'語句,而不是用print語句替換 –

+0

@sundhanshu我試圖滿足要求:不更改代碼:-) –