2012-07-20 30 views
31

我想處理AssertionError這兩個都隱藏用戶的堆棧跟蹤不必要的部分,並打印一條消息,爲什麼發生錯誤和用戶應該做什麼。如何在Python中處理AssertionError,並找出它發生的行或語句?

是否有任何方法可以找出在except塊內assert失敗的行或語句?

try: 
    assert True 
    assert 7 == 7 
    assert 1 == 2 
    # many more statements like this 
except AssertionError: 
    print 'Houston, we have a problem.' 
    print 
    print 'An error occurred on line ???? in statement ???' 
    exit(1) 

我不希望有這種添加到每個斷言語句:

assert 7 == 7, "7 == 7" 

,因爲它重複信息。

+7

兩個問題。首先,如果您無法確定'try..except'中發生異常的位置,那麼這是'try..except'塊太大的標誌。其次,這種被assert抓住的東西不是用戶應該看到的東西。如果他們看到一個'AssertionError',正確的做法是讓他們聯繫程序員並說「WTF ?!」。 – 2012-07-20 21:51:53

+2

@John Y,你好像很困惑。你說'AssertionError's不應該被用戶看到,然後用戶應該做什麼,當他看到一個。它不可能是兩個! – devtk 2012-07-20 22:18:50

+3

BTW:斷言應該是關於你的代碼的結構,也就是說,只有當你的軟件有bug時,斷言纔會失敗。他們不應該用來檢查用戶輸入。您可能會考慮爲此應用程序使用不同的例外。 – 2012-07-21 00:42:50

回答

47

使用traceback模塊:

import sys 
import traceback 

try: 
    assert True 
    assert 7 == 7 
    assert 1 == 2 
    # many more statements like this 
except AssertionError: 
    _, _, tb = sys.exc_info() 
    traceback.print_tb(tb) # Fixed format 
    tb_info = traceback.extract_tb(tb) 
    filename, line, func, text = tb_info[-1] 

    print('An error occurred on line {} in statement {}'.format(line, text)) 
    exit(1) 
1

回溯模塊和sys.exc_info是矯枉過正追蹤異常的來源。這些都在默認回溯中。因此,而不是調用exit(1)只是重新加註:

try: 
    assert "birthday cake" == "ice cream cake", "Should've asked for pie" 
except AssertionError: 
    print 'Houston, we have a problem.' 
    raise 

這給下面的輸出,其中包括有問題的聲明和行號:

Houston, we have a problem. 
Traceback (most recent call last): 
    File "/tmp/poop.py", line 2, in <module> 
    assert "birthday cake" == "ice cream cake", "Should've asked for pie" 
AssertionError: Should've asked for pie 

同樣記錄模塊可以很容易地記錄對於任何異常(包括被捕獲的和從未再次提出的那些異常)的回溯:

import logging 

try: 
    assert False == True 
except AssertionError: 
    logging.error("Nothing is real but I can't quit...", exc_info=True) 
相關問題