由於mechmind回答,堆棧跟蹤僅由所在部位的異常之間的幀被提出和try
塊的網站。如果你需要完整的堆棧跟蹤,顯然你運氣不好。
除了很明顯可以從頂層提取堆棧條目到當前幀 - traceback.extract_stack
管理它就好了。問題是traceback.extract_stack
獲得的信息來自堆棧幀的直接檢查,而不會在任何時候創建回溯對象,並且logging
API需要回溯對象來影響回溯輸出。
幸運的是,logging
不需要實際追蹤的對象,它需要一個對象,它可以傳遞給traceback
模塊的格式化程序。 traceback
也不在乎 - 它只使用追蹤,幀和行號的兩個屬性。所以,應該有可能創建一個duck-typed人造追蹤對象的鏈表並將其作爲追蹤傳遞給它。
import sys
class FauxTb(object):
def __init__(self, tb_frame, tb_lineno, tb_next):
self.tb_frame = tb_frame
self.tb_lineno = tb_lineno
self.tb_next = tb_next
def current_stack(skip=0):
try: 1/0
except ZeroDivisionError:
f = sys.exc_info()[2].tb_frame
for i in xrange(skip + 2):
f = f.f_back
lst = []
while f is not None:
lst.append((f, f.f_lineno))
f = f.f_back
return lst
def extend_traceback(tb, stack):
"""Extend traceback with stack info."""
head = tb
for tb_frame, tb_lineno in stack:
head = FauxTb(tb_frame, tb_lineno, head)
return head
def full_exc_info():
"""Like sys.exc_info, but includes the full traceback."""
t, v, tb = sys.exc_info()
full_tb = extend_traceback(tb, current_stack(1))
return t, v, full_tb
有了這些功能,您的代碼只需要一個簡單的修改:
import logging
def func():
try:
raise Exception('Dummy')
except:
logging.error("Something awful happened!", exc_info=full_exc_info())
def func2():
func()
func2()
...得到所需要的輸出:
ERROR:root:Something awful happened!
Traceback (most recent call last):
File "a.py", line 52, in <module>
func2()
File "a.py", line 49, in func2
func()
File "a.py", line 43, in func
raise Exception('Dummy')
Exception: Dummy
注意的是,人造回溯對象完全可用於自省 - 顯示局部變量或作爲參數pdb.post_mortem()
,因爲它們包含對真實堆棧幀的引用。
[如何將traceback/sys.exc \ _info()值保存在變量中?](http://stackoverflow.com/questions/8238360/how-to-save-traceback-sys-exc- info-values-in-a-variable) – Nathan
@Nathan,請仔細閱讀這個問題。 **完整**追蹤是必要的。 – warvariuc
請參閱[在Python中爲異常生成完整堆棧跟蹤](http://blog.dscpl.com.au/2015/03/generating-full-stack-traces-for.html)由Graham Dupleton撰寫的博客文章。 –