2012-11-03 23 views
23

func2 और func फ़ंक्शंस की कॉल सहित, निम्नलिखित मामले में मुझे पूर्ण ट्रेसबैक कैसे मिल सकता है?पूर्ण ट्रेसबैक प्राप्त करें

import traceback 

def func(): 
    try: 
     raise Exception('Dummy') 
    except: 
     traceback.print_exc() 

def func2(): 
    func() 


func2() 

जब मैं इस चलाने के लिए, मैं मिलता है:

Traceback (most recent call last): 
    File "test.py", line 5, in func 
    raise Exception('Dummy') 
Exception: Dummy 

traceback.format_stack() के रूप में की जरूरत traceback वस्तु एक तीसरी पार्टी मॉड्यूल को पास करने की नहीं है मैं क्या चाहते हैं,।

मैं विशेष रूप से इस मामले में दिलचस्पी है:

import logging 


def func(): 
    try: 
     raise Exception('Dummy') 
    except: 
     logging.exception("Something awful happened!") 


def func2(): 
    func() 


func2() 

इस मामले में मैं हो रही है:

ERROR:root:Something awful happened! 
Traceback (most recent call last): 
    File "test.py", line 9, in func 
    raise Exception('Dummy') 
Exception: Dummy 
+0

संभावित डुप्लिकेट [एक चर में traceback/sys.exc \ _info() मानों को कैसे सहेजना है?] (Http://stackoverflow.com/questions/8238360/how-to-save-traceback-sys-exc- जानकारी-मूल्य-इन-ए-वेरिएबल) – Nathan

+0

@ नाथन, कृपया प्रश्न को सावधानी से दोबारा पढ़ें। ** पूर्ण ** ट्रेसबैक की आवश्यकता है। – warvariuc

+2

देखें [पायथन में अपवादों के लिए पूर्ण स्टैक निशान उत्पन्न करना।] (Http://blog.dscpl.com.au/2015/03/generating-full-stack-traces-for.html) ग्राहम डुप्लेटन द्वारा ब्लॉग पोस्ट। –

उत्तर

32

mechmind जवाब के रूप में, स्टैक ट्रेस केवल साइट है, जहां अपवाद के बीच फ्रेम के होते हैं उठाया गया था और try ब्लॉक की साइट। यदि आपको पूर्ण स्टैक ट्रेस की ज़रूरत है, तो जाहिर है कि आप भाग्य से बाहर हैं।

सिवाय इसके कि शीर्ष स्तर से वर्तमान फ्रेम तक स्टैक प्रविष्टियों को निकालना संभव है- traceback.extract_stack इसे ठीक से प्रबंधित करता है। समस्या यह है कि traceback.extract_stack द्वारा प्राप्त जानकारी किसी भी बिंदु पर ट्रेसबैक ऑब्जेक्ट के बिना स्टैक फ्रेम के प्रत्यक्ष निरीक्षण से आता है, और logging एपीआई को ट्रेसबैक आउटपुट को प्रभावित करने के लिए ट्रेसबैक ऑब्जेक्ट की आवश्यकता होती है।

सौभाग्य से, logging एक वास्तविक ट्रैस बैक वस्तु की आवश्यकता नहीं है, यह एक वस्तु की आवश्यकता है कि यह traceback मॉड्यूल के स्वरूपण दिनचर्या को पारित कर सकते हैं। traceback या तो परवाह नहीं करता है-यह केवल ट्रेसबैक, फ्रेम और रेखा संख्या के दो विशेषताओं का उपयोग करता है। इसलिए, बतख-टाइप की गई फॉक्स-ट्रेसबैक ऑब्जेक्ट्स की एक लिंक की गई सूची बनाना और ट्रेसबैक के रूप में इसे पास करना संभव होना चाहिए।

import logging 

def func(): 
    try: 
     raise Exception('Dummy') 
    except: 
     logging.error("Something awful happened!", exc_info=full_exc_info()) 

def func2(): 
    func() 

func2() 

... अपेक्षित आउटपुट देने के लिए:

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 
जगह में इन कार्यों के साथ

, अपने कोड केवल एक छोटी सी संशोधन की आवश्यकता है

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() पर तर्क के रूप में - क्योंकि वे असली स्टैक फ्रेम के संदर्भ हैं।

+1

मुझे यह जानकारी पता है। यदि आप फिर से मेरे प्रश्न को देखते हैं, तो आप ['logging.exception'] (http://docs.python.org/2/library/logging.html#logging.Logger.exception) का उपयोग करेंगे जो कि एक शॉर्टकट है तुमने क्या लिखा। – warvariuc

+0

@warwaruk आप बिल्कुल सही हैं। आपके प्रश्न का मुद्दा यह है कि एक कोशिश/छोड़कर ब्लॉक स्टैक ट्रेस को छोटा करता है, और आप पूर्ण एक चाहते हैं। मुझे विश्वास नहीं है कि मैंने इसे पहले कभी नहीं देखा है। – user4815162342

+1

@warwaruk मैंने अब वास्तव में आपके प्रश्न का उत्तर देने के लिए उत्तर अपडेट किया है। अगर ऐसा करने का कोई आसान तरीका है, तो मैं इसे भी जानना चाहता हूं। – user4815162342

3

अपवाद बुलबुले होने पर स्टैक ट्रेस एकत्र किया जाता है। तो आप इच्छित ढेर के शीर्ष पर ट्रैस बैक प्रिंट चाहिए:

import traceback 

def func(): 
    raise Exception('Dummy') 

def func2(): 
    func() 


try: 
    func2() 
except: 
    traceback.print_exc() 
+2

समस्या यह है कि यह अर्थशास्त्र बदलता है। यदि ओपी 'func2' विफल रहता है तो 'func'' विफल रहता है (और ट्रेसबैक लॉग करें), अपवाद को 'func2' में संभाला जाना चाहिए, इसके बाहर नहीं। – user4815162342

-1

कुछ और जानकारी है कि ट्रैस बैक से निकाला जा सकता है, और मैं कभी कभी एक neater, अधिक 'तर्कसंगत' फाइलों के साथ बहु लाइन ब्लॉब के बजाय जानकारी पसंद करते हैं , ट्रेसबैक द्वारा लाइन नंबर और कोड स्निपेट्सगिवेन। अधिमानतः एक पंक्ति को सभी आवश्यक बातें कहना चाहिए।

इस लक्ष्य को हासिल करने के लिए मैं समारोह निम्नलिखित का उपयोग करें:

def raising_code_info(): 
    code_info = '' 
    try:  
     frames = inspect.trace() 
     if(len(frames)): 
      full_method_name = frames[0][4][0].rstrip('\n\r').strip() 
      line_number  = frames[1][2] 
      module_name  = frames[0][0].f_globals['__name__'] 
      if(module_name == '__main__'): 
       module_name = os.path.basename(sys.argv[0]).replace('.py','') 
      class_name = '' 
      obj_name_dot_method = full_method_name.split('.', 1) 
      if len(obj_name_dot_method) > 1: 
       obj_name, full_method_name = obj_name_dot_method 
       try: 
        class_name = frames[0][0].f_locals[obj_name].__class__.__name__ 
       except: 
        pass 
      method_name = module_name + '.' 
      if len(class_name) > 0: 
       method_name += class_name + '.' 
      method_name += full_method_name 
      code_info = '%s, line %d' % (method_name, line_number) 
    finally: 
     del frames 
     sys.exc_clear() 
    return code_info 

यह देता है। और रेखा संख्या, उदा।:

(उदाहरण के मॉड्यूल का नाम: test.py):

(line 73:) 
def function1(): 
    print 1/0 

class AClass(object):  
    def method2(self): 
     a = [] 
     a[3] = 1 

def try_it_out(): 
    # try it with a function 
    try: 
     function1() 
    except Exception, what: 
     print '%s: \"%s\"' % (raising_code_info(), what) 

    # try it with a method 
    try: 
     my_obj_name = AClass() 
     my_obj_name.method2()  
    except Exception, what: 
     print '%s: \"%s\"' % (raising_code_info(), what) 

if __name__ == '__main__': 
    try_it_out() 


test.function1(), line 75: "integer division or modulo by zero" 
test.AClass.method2(), line 80: "list assignment index out of range" 

जो थोड़ा neater कुछ उपयोग-मामले में हो सकता है।

+0

मैंने आपके कोड की जांच नहीं की है, मुझे विश्वास है कि यह काम करता है। लेकिन सवाल में यह कहा गया है: "traceback.format_stack()' मैं जो चाहता हूं वह नहीं है, क्योंकि किसी तीसरे पक्ष के मॉड्यूल में 'traceback' ऑब्जेक्ट को पारित करने की आवश्यकता है। " वैसे भी एक और कोड स्निपेट के लिए धन्यवाद। – warvariuc

1

मैं एक मॉड्यूल है कि एक और अधिक पूरा ट्रैस बैक लिखते लिखा है

मॉड्यूल here प्रलेखन docs

(भी आप pypi से मॉड्यूल

sudo pip install pd 

प्राप्त कर सकते हैं) है

पकड़ने और छेड़छाड़ करने के लिए निम्नलिखित कार्य करें:

import pd 

try: 
    <python code> 
except BaseException:  
    pd.print_exception_ex(follow_objects = 1) 

स्टैक ट्रेस इस एक यहाँ दिखाई देता है:

Exception: got it 

#1 def kuku2(self = {'a': 42, 'b': [1, 2, 3, 4]}, depth = 1) at  t test_pd.py:29 
Calls next frame at: 
    raise Exception('got it') at: test_pd.py:29 

#2 def kuku2(self = {'a': 42, 'b': [1, 2, 3, 4]}, depth = 2) at test_pd.py:28 
Calls next frame at: 
    self.kuku2(depth - 1) at: test_pd.py:28 

#3 def kuku2(self = {'a': 42, 'b': [1, 2, 3, 4]}, depth = 3) at test_pd.py:28 
Calls next frame at: 
    self.kuku2(depth - 1) at: test_pd.py:28 

#4 def kuku2(self = {'a': 42, 'b': [1, 2, 3, 4]}, depth = 4) at test_pd.py:28 
Calls next frame at: 
    self.kuku2(depth - 1) at: test_pd.py:28 

#5 def kuku2(self = {'a': 42, 'b': [1, 2, 3, 4]}, depth = 5) at  test_pd.py:28 
Calls next frame at: 
    self.kuku2(depth - 1) at: test_pd.py:28 

#6 def kuku2(self = {'a': 42, 'b': [1, 2, 3, 4]}, depth = 6) at test_pd.py:28 
Calls next frame at: 
    self.kuku2(depth - 1) at: test_pd.py:28 

#7 def main() at test_pd.py:44 
Local variables: 
n = {'a': 42, 'b': [1, 2, 3, 4]} 
Calls next frame at: 
    pd.print_exception_ex(follow_objects = 1) at: test_pd.py:44 

follow_objects = 0 वस्तु सामग्री मुद्रित नहीं होगा (जटिल डेटा संरचनाओं follow_objects साथ बहुत समय लग सकता है)।

+0

फ़ाइल "एफ: \ पायथन \ lib \ site-packages \ pd \ pdd.py", लाइन 18 वापसी मूल्य ^ टैबरर: इंडेंटेशन में टैब और रिक्त स्थान का असंगत उपयोग – user

संबंधित मुद्दे