2014-03-06 40 views
2

如何確定引發了哪個函數異常。例如存在兩個功能:'foo'和'bar'。在'foo'中,異常會隨機提出。如何在Python中找到引發異常的位置

import random 


def foo(): 
    if random.randint(1, 10) % 2: 
     raise Exception 
    bar() 


def bar(): 
    raise Exception 

try: 
    foo() 
except Exception as e: 
    print "Exception raised in %s" % ??? 
+0

如果這是一個純粹的「學院派」的問題,爲什麼不呢,但是您不應該依賴像在實際生活代碼中檢查堆棧跟蹤等內容......而是使用自定義異常類(或許多內置函數之一)更好。 –

+0

是的,它只是有趣的 – Habibutsu

回答

6
import inspect 

try: 
    foo() 
except Exception as e: 
    print "Exception raised in %s" % inspect.trace()[-1][3] 
+0

這可能是提問者的意思,但它可能不是最好的現實生活方案:) –

2

我使用追蹤模塊,像這樣:

import traceback 

try: 
    1/0 
except Exception: 
    print traceback.format_exc() 

這給出了以下的輸出:

Traceback (most recent call last): 
    File "<ipython-input-3-6b05b5b621cb>", line 2, in <module> 
    1/0 
ZeroDivisionError: integer division or modulo by zero 

如果代碼從一個文件運行時,回溯會告訴錯誤發生的地方的行號和字符號:)

編輯:

Habibutsu容納註釋:Yes, it's useful for printing, but when needed to get more info (for example function name) - not suitable

的文檔的頁面告訴你如何提取編程軌跡:http://docs.python.org/2/library/traceback.html

從上面的鏈接頁面:

>>> import traceback 
>>> def another_function(): 
...  lumberstack() 
... 
>>> def lumberstack(): 
...  traceback.print_stack() 
...  print repr(traceback.extract_stack()) 
...  print repr(traceback.format_stack()) 
... 
>>> another_function() 
    File "<doctest>", line 10, in <module> 
    another_function() 
    File "<doctest>", line 3, in another_function 
    lumberstack() 
    File "<doctest>", line 6, in lumberstack 
    traceback.print_stack() 
[('<doctest>', 10, '<module>', 'another_function()'), 
('<doctest>', 3, 'another_function', 'lumberstack()'), 
('<doctest>', 7, 'lumberstack', 'print repr(traceback.extract_stack())')] 
[' File "<doctest>", line 10, in <module>\n another_function()\n', 
' File "<doctest>", line 3, in another_function\n lumberstack()\n', 
' File "<doctest>", line 8, in lumberstack\n print repr(traceback.format_stack())\n'] 

traceback.extract_stack的文檔字符串與traceback.extract_tb

traceback.extract_tb(回溯[,極限])

返回高達限制從回溯對象追蹤提取的「預處理」堆棧跟蹤條目 列表。它對於堆棧跟蹤的替代格式是有用的 。如果省略了限制或無,則提取所有 條目。 「預處理」堆棧跟蹤條目是一個 四位(文件名,行號,函數名稱,文本),表示 通常爲堆棧跟蹤打印的信息。文本是 一個字符串,前導和尾隨空白被剝離;如果源 不可用,則爲無。

+0

是的,它對打印很有用,但是當需要獲取更多信息時(例如函數名稱) - 不適合 – Habibutsu

+0

@Habibutsu我更新了我的答案,向您展示了'traceback'確實是否合適,並且可以用於提取函數名稱,例如:) –

2

你的目標是?如果你擔心barfoo拋出同樣的異常類型,不能夠區分它們的調用者,只是派生出新的異常類:

import random 

class FooException(Exception): 
    """An exception thrown only by foo.""" 

def foo(): 
    if random.randint(1,10) % 2: 
     raise FooException 

    bar() 

def bar(): 
    raise Exception 

try: 
    foo() 
except FooException: 
    print "Exception raised in foo..." 
except: 
    print "Exception raised in bar (probably)..." 
+0

我同意您的方法更好,但它不適用於您收到的回調用戶。或者例如RPC,當TypeError可能會在嘗試調用函數或其內部時引發。 其實現在我不建立依賴這些信息的邏輯,但它很有趣。 – Habibutsu

+0

您可以將每個回調包裝在引發您的自定義異常的代碼中。 – jme

+0

在這種情況下,如果只是沒有將其包含在新的 – Habibutsu