2012-01-25 15 views
19

को संरक्षित कैसे करें मैं एक फ़ंक्शन पर लागू करने के लिए एक सजावट लिख रहा हूं। इसे किसी भी अपवाद को पकड़ना चाहिए, और फिर मूल अपवाद संदेश के आधार पर एक कस्टम अपवाद उठाएं। (ऐसा इसलिए है क्योंकि सूड एक सामान्य वेबफॉल्ट अपवाद फेंकता है, जिसका संदेश मैं वेब सेवा द्वारा अपवाद को अपवादित करता हूं और इसे दर्पण करने के लिए पाइथन अपवाद बढ़ाता हूं।)पायथन: अपवाद सजावट। Stacktrace

हालांकि, जब मैं रैपर में कस्टम अपवाद बढ़ाता हूं, तो मैं चाहते हैं कि स्टैकट्रैक उस कार्य को इंगित करे जो मूल वेबफॉल्ट अपवाद उठाता है। जो मैंने अभी तक सही अपवाद उठाया है (यह गतिशील रूप से संदेश को पारदर्शी करता है और अपवाद वर्ग को तत्काल करता है)। मेरा प्रश्न: वेबफॉल्ट अपवाद को उठाए गए मूल फ़ंक्शन को इंगित करने के लिए मैं स्टैकट्रैक को कैसे संरक्षित कर सकता हूं?

from functools import wraps 

def try_except(fn): 
     def wrapped(*args, **kwargs): 
      try: 
       fn(*args, **kwargs) 
      except Exception, e: 
       parser = exceptions.ExceptionParser() 
       raised_exception = parser.get_raised_exception_class_name(e) 
       exception = getattr(exceptions, raised_exception) 
       raise exception(parser.get_message(e)) 
     return wraps(fn)(wrapped) 
+1

आप 'traceback' मॉड्यूल को देखा है:

मैं डेकोरेटर शरीर में निर्माण मूल का पता लगाने unittests उत्पादन में मुद्रित संरक्षित करने के लिए निम्नलिखित का इस्तेमाल किया? http://docs.python.org/library/traceback.html – stderr

+0

सजावट में लपेटते समय [functools.wrap] (https://docs.python.org/2/library/functools.html) –

+0

संभावित डुप्लिकेट [पाइथन में "आंतरिक अपवाद" (ट्रेसबैक के साथ)? (Http://stackoverflow.com/questions/1350671/inner-exception-with-traceback-in-python) –

उत्तर

37

पायथन 2.x में, raise की एक अल्पज्ञात विशेषता है कि यह तर्क सिर्फ एक की तुलना में अधिक के साथ इस्तेमाल किया जा सकता है: raise के तीन तर्क प्रपत्र अपवाद प्रकार, अपवाद उदाहरण और ले जाता है वापस ट्रेस करें। आप sys.exc_info() के साथ ट्रेसबैक पर जा सकते हैं, जो अपवाद प्रकार, अपवाद उदाहरण और ट्रेसबैक लौटाता है (संयोग से नहीं)।

(कारण इस व्यवहार करता है अपवाद प्रकार और दो अलग-अलग तर्कों के रूप अपवाद उदाहरण अपवाद कक्षाओं से पहले के दिनों से एक विरूपण साक्ष्य है।)

तो:

import sys 

class MyError(Exception): 
    pass 

def try_except(fn): 
    def wrapped(*args, **kwargs): 
     try: 
      return fn(*args, **kwargs) 
     except Exception, e: 
      et, ei, tb = sys.exc_info() 
      raise MyError, MyError(e), tb 
    return wrapped 

def bottom(): 
    1/0 

@try_except 
def middle(): 
    bottom() 

def top(): 
    middle() 

>>> top() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "tmp.py", line 24, in top 
    middle() 
    File "tmp.py", line 10, in wrapped 
    return fn(*args, **kwargs) 
    File "tmp.py", line 21, in middle 
    bottom() 
    File "tmp.py", line 17, in bottom 
    1/0 
__main__.MyError: integer division or modulo by zero 

अजगर 3 में, यह बदल गया थोड़ा सा। वहाँ, ट्रेस बैक अपवाद उदाहरण के बजाय जुड़े होते हैं, और वे एक with_traceback विधि है:

raise MyError(e).with_traceback(tb) 

दूसरी ओर अजगर 3 पर भी अपवाद चेनिंग है, जो कई मामलों में अधिक समझ में आता है है; इसका उपयोग करने के लिए, आप बस उपयोग करेंगे:

raise MyError(e) from e 
+0

बढ़िया, धन्यवाद! यह काम किया। केवल मुद्दा यह था कि मुझे सजावट को सजाए जाने के समान ही फाइल में सजावट को स्थानांतरित करना था, अन्यथा sys.exc_info() लौटा (कोई नहीं, कोई नहीं, कोई नहीं) - कोई विचार यह क्यों होगा? – igniteflow

+0

वह ... समझ में नहीं आता है। sys.exc_info() परवाह नहीं है जहां कॉलर परिभाषित किया गया है। यह वर्तमान में होने वाले हैंडल अपवाद देता है। ऐसा लगता है कि आपके पास एक अलग फ़ाइल में सजावट करने वाला सही काम नहीं कर रहा था, लेकिन वास्तविक कोड को देखे बिना कहना मुश्किल है। –

4

मुझे इस समस्या का सामना करना पड़ रहा है जो मेरे कस्टम सजावट से सजाए गए थे।

try: 
    result = func(self, *args, **kwargs) 
except Exception: 
    exc_type, exc_instance, exc_traceback = sys.exc_info() 
    formatted_traceback = ''.join(traceback.format_tb(
     exc_traceback)) 
    message = '\n{0}\n{1}:\n{2}'.format(
     formatted_traceback, 
     exc_type.__name__, 
     exc_instance.message 
    ) 
    raise exc_type(message) 
+0

हाँ लेकिन सजावट के लिए तर्क क्या हैं? –

+0

बस यह इंगित करने के लिए कि उपरोक्त कोड के साथ अंतर 'traceback.format_tb' है। धन्यवाद। – Ehvince

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