अजगर "उपयोग" से उठाएं


196

पायथन में raiseऔर क्या अंतर है raise from?

try:
    raise ValueError
except Exception as e:
    raise IndexError

कौन सी पैदावार

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    raise ValueError
ValueError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    raise IndexError
IndexError

तथा

try:
    raise ValueError
except Exception as e:
    raise IndexError from e

कौन सी पैदावार

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    raise ValueError
ValueError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    raise IndexError from e
IndexError

9
क्या आपने PEP-3134 पढ़ा है ?
जोनरशेप

4
अब उपयोग करो raise IndexError from None, कहो।
मार्टिजन पीटरर्स

11
हे। raise IndexError from Falseएक उठाता है TypeError, ए नहीं IndexError। मेरा दिन बना दिया।
मैड फिजिसिस्ट


यकीन नहीं होता कि यह उल्लेख करने के लिए सही जगह है, लेकिन स्पाइडर का उपयोग करने वाले किसी को भी: यह पूरा निर्माण वहां काम नहीं करता है। यह अब 3 साल से अधिक के लिए एक मुद्दा है ( github.com/spyder-ide/spyder/issues/2943 ), लेकिन उन्हें लगता है कि जंजीरों के अपवाद की कोई आवश्यकता नहीं है।
एमिल बोडे

जवाबों:


228

अंतर यह है कि जब आप उपयोग करते हैं from, तो __cause__विशेषता सेट की जाती है और संदेश बताता है कि अपवाद सीधे कारण था । यदि आप छोड़ देते हैं fromतो कोई __cause__सेट नहीं किया जाता है, लेकिन __context__विशेषता के रूप में अच्छी तरह से सेट किया जा सकता है, और ट्रेसबैक तब संदर्भ को दिखाता है जैसे कि कुछ हुआ था

__context__यदि आप raiseअपवाद हैंडलर में उपयोग करते हैं तो सेटिंग करना ; यदि आप raiseकहीं और इस्तेमाल करते हैं तो कोई __context__भी सेट नहीं है।

यदि कोई __cause__सेट है, __suppress_context__ = Trueतो अपवाद पर एक ध्वज भी सेट किया गया है; जब __suppress_context__सेट किया जाता है True, तो __context__ट्रेसबैक प्रिंट करते समय इसे अनदेखा कर दिया जाता है।

जब एक अपवाद संचालक जहां से ऊपर उठाने में नहीं आता संदर्भ दिखाना चाहते हैं (नहीं है एक चाहते से निपटने एक और अपवाद हुआ दौरान , तो का उपयोग संदेश) raise ... from Noneसेट करने के लिए __suppress_context__करने के लिए True

दूसरे शब्दों में, पायथन अपवादों पर एक संदर्भ निर्धारित करता है ताकि आप आत्मनिरीक्षण कर सकें कि एक अपवाद कहां उठाया गया था, आपको यह देखने देता है कि क्या कोई अन्य अपवाद इसके द्वारा प्रतिस्थापित किया गया था। आप एक अपवाद का कारण भी जोड़ सकते हैं , जिससे अन्य अपवाद के बारे में ट्रेसबैक स्पष्ट हो जाता है (विभिन्न शब्दों का उपयोग करें), और संदर्भ को नजरअंदाज कर दिया जाता है (लेकिन डिबगिंग के दौरान अभी भी आत्मनिरीक्षण किया जा सकता है)। उपयोग raise ... from Noneकरने से आप मुद्रित होने वाले संदर्भ को दबा सकते हैं।

raiseकथन को देखें :

fromखंड अपवाद श्रृंखलन के लिए प्रयोग किया जाता है: यदि दिया, दूसरी अभिव्यक्ति एक और अपवाद वर्ग या उदाहरण है, जो तब के रूप में उठाया अपवाद के साथ संलग्न किया जाएगा होना चाहिए __cause__(जो लिखने योग्य है) विशेषता। यदि उठाए गए अपवाद को नियंत्रित नहीं किया जाता है, तो दोनों अपवाद मुद्रित होंगे:

>>> try:
...     print(1 / 0)
... except Exception as exc:
...     raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

यदि समान अपवाद हैंडलर या finallyक्लॉज के अंदर उठाया जाता है, तो एक समान तंत्र कार्य करता है : पिछले अपवाद को फिर नए अपवाद की __context__विशेषता के रूप में संलग्न किया जाता है :

>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

यह भी देखें निर्मित अपवाद प्रलेखन अपवाद से जुड़ी संदर्भ और कारण सूचना के आधार पर जानकारी के लिए।


11
तो ऐसा कोई कारण स्पष्ट रूप से उपयोग करके अपवादों को श्रृंखला के लिए है fromऔर __cause__निहित के एवज में __context__? क्या ऐसे कोई मामले हैं, जहां कोई व्यक्ति द्वारा पकड़े गए की तुलना में एक अलग अपवाद संलग्न करेगा except?
डार्कफ्लीन

13
@darkfeline: बताएं कि आपका डेटाबेस API वेब और डिस्क सहित विभिन्न स्रोतों से डेटाबेस खोलने का समर्थन करता है। डेटाबेस के विफल होने पर आपका API हमेशा बढ़ा रहेगा DatabaseError। लेकिन यदि विफलता एक परिणाम के रूप में है, IOErrorक्योंकि फ़ाइल खोलने में विफल रही या HTTPErrorक्योंकि URL काम करने में विफल रहा है, तो वह संदर्भ है जिसे आप स्पष्ट रूप से शामिल करना चाहते हैं, इसलिए API का उपयोग करने वाला डेवलपर यह डिबग कर सकता है कि यह क्यों है। उस क्षण तुम उपयोग करते हो raise DatabaseError from original_exception
मार्टिन पीटर्स

4
@darkfeline: यदि वह डेवलपर डेटाबेस API का उपयोग अपने API में कर रहा है और उस पर IOErrorया अपने उपभोक्ताओं को पास करना चाहता है , तो उन्हें इसका उपयोग करना होगा , अब इससे अलग अपवाद का उपयोग करते हुए वे बस पकड़े गए। HTTPErrorraise NewException from databaseexception.__cause__DatabaseException
मार्टिन पीटर्स

2
@ dan3: नहीं, वहाँ नहीं है। अपवाद चेनिंग विशुद्ध रूप से पायथन 3 सुविधा है।
मार्टिन पीटर्स

5
@ laike9m: आपका मतलब है जब आप अपवाद को संभाल रहे हैं foo, और एक नया अपवाद उठाना चाहते हैं bar? फिर आप raise bar from fooपाइथन राज्य का उपयोग और उपयोग कर सकते हैं जो foo सीधे कारण होता हैbar । यदि आप उपयोग नहीं करते हैं from foo, तो पायथन अभी भी दोनों को प्रिंट करेगा, लेकिन बताता है कि हैंडलिंग के दौरान foo,bar त्रुटि संदेश में संभव बग को चिह्नित करने के लिए अलग संदेश, उठाया गया था
मार्टिन पीटर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.