2011-06-08 13 views
26

में अपवाद पहले से मौजूद होने पर अपवाद उठा रहा है मेरे दूसरे अपवाद (A) का क्या होता है जब दूसरा (B) निम्न कोड में उठाया जाता है?पाइथन 3

class A(Exception): pass 
class B(Exception): pass 

try: 
    try: 
     raise A('first') 
    finally: 
     raise B('second') 
except X as c: 
    print(c) 

X = A साथ चलाते हैं मैं:

Traceback (most recent call last): 
    File "raising_more_exceptions.py", line 6, in 
    raise A('first') 
__main__.A: first 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "raising_more_exceptions.py", line 8, in 
    raise B('second') 
__main__.B: second

लेकिन अगर X = B मैं:

second

प्रश्न

  1. कहाँ मेरा पहला अपवाद चली गई?
  2. केवल बाहरी अपवाद को पकड़ने योग्य क्यों है?
  3. मैं बाहरी अपवाद को कैसे छील सकता हूं और पहले के अपवादों का पुन: उपयोग कैसे करूं?

Update0

यह सवाल विशेष रूप से, पते, अजगर 3 के रूप में अपनी अपवाद हैंडलिंग पायथन 2.

+0

उत्तर इस तथ्य की उपेक्षा कर रहे हैं कि अपवाद पकड़ा जाने पर मुझे अभी भी पूर्ण ट्रेसबैक मिल रहा है। कृपया समझाएँ? –

उत्तर

6
  1. यह बाहर फेंक दिया गया करने के लिए काफी अलग है।
  2. प्रति थ्रेड के समय केवल एक अपवाद "सक्रिय" हो सकता है।
  3. आप तब तक नहीं कर सकते जब तक आप किसी भी तरह के अपवाद में पहले अपवाद को समाहित नहीं करते।
+1

अगर इसे बाहर निकाला गया है, तो अपवाद पकड़ा जाने पर मुझे पूर्ण ट्रेसबैक क्यों मिल रहा है? –

+0

क्योंकि जिस स्क्रिप्ट को आप स्क्रिप्ट चलाने के लिए उपयोग कर रहे हैं, ने वैश्विक अपवाद हैंडलर स्थापित किया है, और इसमें डबल अपवाद देखा गया है। –

+1

क्या उपकरण .....? –

8

पायथन अपवाद हैंडलिंग केवल एक समय में एक अपवाद के साथ सौदा करेगा। हालांकि, अपवाद ऑब्जेक्ट्स वही परिवर्तनीय नियमों और कचरा संग्रह के अधीन हैं जो बाकी सब कुछ के रूप में हैं। इसलिए, यदि आप कहीं भी एक चर में अपवाद ऑब्जेक्ट को सहेजते हैं तो आप बाद में इसका सामना कर सकते हैं, भले ही कोई अन्य अपवाद उठाया गया हो।

आपके मामले में, जब "अंततः" कथन के दौरान अपवाद उठाया जाता है, तो पाइथन 3 दूसरे अपवाद में से एक के पहले अपवाद के पहले ट्रेसबैक को अधिक सहायक होने के लिए प्रिंट करेगा।

एक और आम मामला यह है कि आप एक स्पष्ट अपवाद हैंडलिंग के दौरान अपवाद उठाना चाहते हैं। फिर आप अगले अपवाद में अपवाद को "सेव" कर सकते हैं। बस इसे पैरामीटर के रूप में पास करें:

>>> class A(Exception): 
...  pass 
... 
>>> class B(Exception): 
...  pass 
... 
>>> try: 
...  try: 
...   raise A('first') 
...  except A as e: 
...   raise B('second', e) 
... except Exception as c: 
...  print(c.args[1]) 
... 
first 

जैसा कि आप देखते हैं कि अब आप मूल अपवाद तक पहुंच सकते हैं।

+0

क्या आप भाग 1 का जवाब दे सकते हैं? –

+0

@ मैट: यह कहीं भी नहीं जाता है। मुझे एहसास है कि मेरे पास एक मस्तिष्क था और मेरा जवाब अपडेट किया गया, हालांकि। –

+0

कोई इस स्थिति को सिद्धांतों में कैसे संभालता है? – hayavuk

5

मुझे विश्वास है कि आपके प्रश्नों का उत्तर देने के लिए सभी सामग्री पहले से ही मौजूदा उत्तरों में हैं। मुझे गठबंधन और विस्तृत करने दें।

मुझे लाइन नंबर संदर्भ प्रदान करने के लिए अपने प्रश्न के कोड दोहराएँ:

1 class A(Exception): pass 
2 class B(Exception): pass 
3 
4 try: 
5  try: 
6   raise A('first') 
7  finally: 
8   raise B('second') 
9 except X as c: 
10  print(c) 

तो आपके सवालों के जवाब:

  1. कहाँ मेरा पहला अपवाद चली गई?

आपका पहला अपवाद A लाइन 6 में उठाया गया है।finally लाइन 7 में क्लॉज हमेशा को try ब्लॉक (लाइन 5-6) के रूप में निष्पादित किया जाता है, भले ही इसे सफल समापन या उठाए गए अपवाद के कारण छोड़ा गया हो। जबकि finally खंड निष्पादित किया जा रहा है, लाइन 8 एक और अपवाद B उठाता है। जैसा कि लेनार्ट और इग्नाज़ियो ने इंगित किया है, केवल एक अपवाद है, जिसे हाल ही में उठाया जा रहा है, का ट्रैक रखा जा सकता है। तो जैसे ही B उठाया गया है, कुल try ब्लॉक (रेखाएं 4-8) को छोड़ दिया गया है और अपवाद Bexcept कथन द्वारा लाइन 9 में पकड़ा जा रहा है यदि यह मेल खाता है (यदि XB है)।

  1. केवल बाहरीतम अपवाद को पकड़ने योग्य क्यों है?

उम्मीद है कि यह अब मेरी व्याख्या से स्पष्ट है 1. हालांकि आप आंतरिक/निचले/पहले अपवाद को पकड़ सकते हैं।

class A(Exception): pass 
class B(Exception): pass 
try: 
    try: 
     raise A('first') 
    except A as e: 
     raise B('second', e) 
except Exception as c: 
    print(c) 

उत्पादन होता है:

('second', A('first',)) 
  1. मैं कैसे सबसे बाहरी अपवाद बंद छील करते Lennart के जवाब में मर्ज करने के लिए, थोड़ा संशोधित, यहाँ दोनों को पकड़ने के लिए तरीका बताया गया है और पहले के अपवादों का पुनर्मूल्यांकन?

Lennart के उदाहरण में इस सवाल का हल लाइन except A as e जहां आंतरिक/कम/पहला अपवाद पकड़ा जा रहा है और चर e में जमा हो जाती है।

अपवादों को कब पकड़ना है, उन्हें कब अनदेखा करना है, और फिर से उठाने के लिए, शायद this question and Alex Martelli's answer सहायता की सामान्य आंत महसूस के रूप में।

7

'कारण' अपवाद आपके अंतिम अपवाद हैंडलर में c .__ context__ के रूप में उपलब्ध है। पाइथन इस जानकारी का उपयोग अधिक उपयोगी ट्रेसबैक प्रस्तुत करने के लिए कर रहा है। पायथन 2.x के तहत मूल अपवाद खो गया होगा, यह केवल पायथन 3 के लिए है।

आमतौर पर आप इस का प्रयोग करेंगे, जबकि अभी भी मूल अपवाद सुलभ बना रहता है एक सुसंगत अपवाद फेंकने के लिए (हालांकि यह बहुत अच्छा है कि यह अपवाद संचालक से स्वचालित रूप से होता है, मुझे लगता है कि पता नहीं था!):

try: 
    do_something_involving_http() 
except (URLError, socket.timeout) as ex: 
    raise MyError('Network error') from ex 

अधिक जानकारी (और कुछ अन्य बहुत उपयोगी चीजें आप कर सकते हैं) यहाँ: http://docs.python.org/3.3/library/exceptions.html

3

3 पर सवाल उठाने का जवाब है, तो आप उपयोग कर सकते हैं:

raise B('second') from None 

जो अपवाद A ट्रेसबैक को हटा देगा।

Traceback (most recent call last): 
    File "raising_more_exceptions.py", line 8, in 
    raise B('second') 
__main__.B: second