जवाबों:
मैं पायथन में अपवाद को मैन्युअल रूप से कैसे फेंक / बढ़ा सकता हूं?
सबसे विशिष्ट अपवाद निर्माणकर्ता का उपयोग करें जो आपके मुद्दे को शब्दार्थ रूप से फिट करता है ।
अपने संदेश में विशिष्ट बनें, जैसे:
raise ValueError('A very specific bad thing happened.')
जेनरिक उठाने से बचें Exception
। इसे पकड़ने के लिए, आपको अन्य सभी विशिष्ट अपवादों को पकड़ना होगा जो इसे उप-वर्ग बनाते हैं।
raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.
उदाहरण के लिए:
def demo_bad_catch():
try:
raise ValueError('Represents a hidden bug, do not catch this')
raise Exception('This is the exception you expect to handle')
except Exception as error:
print('Caught this error: ' + repr(error))
>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)
और अधिक विशिष्ट कैच सामान्य अपवाद को नहीं पकड़ेंगे:
def demo_no_catch():
try:
raise Exception('general exceptions not caught by specific handling')
except ValueError as e:
print('we will not catch exception: Exception')
>>> demo_no_catch()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling
raise
कथनraise ValueError('A very specific bad thing happened')
जो निर्माणकर्ता को पारित करने के लिए मनमाने ढंग से तर्कों की अनुमति देता है:
raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz')
इन तर्कों को ऑब्जेक्ट args
पर विशेषता द्वारा पहुँचा जाता है Exception
। उदाहरण के लिए:
try:
some_code_that_may_raise_our_value_error()
except ValueError as err:
print(err.args)
प्रिंट
('message', 'foo', 'bar', 'baz')
Python 2.5 में, उपयोगकर्ताओं को उप-अपवादों का उपयोग करने के लिए प्रोत्साहित करने और उपयोग करना बंद करने के लिए एक वास्तविक message
विशेषता जोड़ी गई थी , लेकिन args की मूल पदावनति की शुरूआत को हटा दिया गया था ।BaseException
args
message
except
खंडजब एक अपवाद को छोड़कर, आप उदाहरण के लिए चाहते हैं, तो लॉग इन करें कि एक विशिष्ट प्रकार की त्रुटि हुई है, और फिर पुन: बढ़ाएं। स्टैक ट्रेस को संरक्षित करते समय ऐसा करने का सबसे अच्छा तरीका एक नंगे उठे बयान का उपयोग करना है। उदाहरण के लिए:
logger = logging.getLogger(__name__)
try:
do_something_in_app_that_breaks_easily()
except AppError as error:
logger.error(error)
raise # just this!
# raise AppError # Don't do this, you'll lose the stack trace!
आप स्टैकट्रेस (और त्रुटि मान) को संरक्षित कर सकते हैं sys.exc_info()
, लेकिन यह तरीका अधिक त्रुटि प्रवण है और पाइथन 2 और 3 के बीच संगतता समस्याएं हैं, raise
फिर से उठाने के लिए एक नंगे का उपयोग करना पसंद करते हैं ।
समझाने के लिए - sys.exc_info()
रिटर्न प्रकार, मूल्य और ट्रेसबैक।
type, value, traceback = sys.exc_info()
यह पायथन 2 में वाक्य रचना है - ध्यान दें कि यह पायथन 3 के साथ संगत नहीं है:
raise AppError, error, sys.exc_info()[2] # avoid this.
# Equivalently, as error *is* the second object:
raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
यदि आप चाहते हैं, तो आप अपने नए उत्थान के साथ क्या कर सकते हैं - उदाहरण के args
लिए नया सेट कर सकते हैं :
def error():
raise ValueError('oops!')
def catch_error_modify_message():
try:
error()
except ValueError:
error_type, error_instance, traceback = sys.exc_info()
error_instance.args = (error_instance.args[0] + ' <modification>',)
raise error_type, error_instance, traceback
और हमने आर्गन्स को संशोधित करते हुए पूरे ट्रेसबैक को संरक्षित किया है। ध्यान दें कि यह सबसे अच्छा अभ्यास नहीं है और यह पायथन 3 में अमान्य सिंटैक्स है (चारों ओर काम करने के लिए अनुकूलता को बनाए रखना बहुत कठिन है)।
>>> catch_error_modify_message()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in catch_error_modify_message
File "<stdin>", line 2, in error
ValueError: oops! <modification>
में अजगर 3 :
raise error.with_traceback(sys.exc_info()[2])
फिर से: मैन्युअल रूप से ट्रेसबैक में हेरफेर करने से बचें। यह कम कुशल और अधिक त्रुटि प्रवण है। और अगर आप थ्रेडिंग का उपयोग कर रहे हैं और sys.exc_info
आपको गलत ट्रेसबैक भी मिल सकता है (विशेषकर यदि आप नियंत्रण प्रवाह के लिए अपवाद हैंडलिंग का उपयोग कर रहे हैं - जिससे मैं बचना चाहूंगा।)
पायथन 3 में, आप अपवादों को श्रृंखलाबद्ध कर सकते हैं, जो ट्रेसबैक को संरक्षित करते हैं:
raise RuntimeError('specific message') from error
जागरूक रहें:
ये आसानी से छिप सकते हैं और उत्पादन कोड में भी जा सकते हैं। आप एक अपवाद उठाना चाहते हैं, और उन्हें करने से एक अपवाद बढ़ जाएगा, लेकिन ऐसा कोई इरादा नहीं है!
पायथन 2 में मान्य है, लेकिन पायथन 3 में निम्नलिखित नहीं है:
raise ValueError, 'message' # Don't do this, it's deprecated!
केवल पायथन (2.4 और उससे कम) के पुराने संस्करणों में मान्य , आप अभी भी लोगों को तार उठाते हुए देख सकते हैं:
raise 'message' # really really wrong. don't do this.
सभी आधुनिक संस्करणों में, यह वास्तव में एक बढ़ाएगा TypeError
, क्योंकि आप एक BaseException
प्रकार नहीं बढ़ा रहे हैं । यदि आप सही अपवाद की जाँच नहीं कर रहे हैं और एक समीक्षक नहीं है जो इस मुद्दे से अवगत है, तो यह उत्पादन में मिल सकता है।
मैं अपने एपीआई के उपभोक्ताओं को चेतावनी देने के लिए अपवाद उठाता हूं अगर वे इसे गलत तरीके से उपयोग कर रहे हैं:
def api_func(foo):
'''foo should be either 'baz' or 'bar'. returns something very useful.'''
if foo not in _ALLOWED_ARGS:
raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))
"मैं उद्देश्य पर एक त्रुटि बनाना चाहता हूं, ताकि यह अपवाद में जाए"
आप अपनी स्वयं की त्रुटि प्रकार बना सकते हैं, यदि आप यह बताना चाहते हैं कि कुछ विशिष्ट आपके आवेदन के साथ गलत है, बस अपवाद पदानुक्रम में उपयुक्त बिंदु को उप-वर्गित करें:
class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''
और उपयोग:
if important_key not in resource_dict and not ok_to_be_missing:
raise MyAppLookupError('resource is missing, and that is not ok.')
raise sys.exc_info()[0], (sys.exc_info()[1], my_extra_info), sys.exc_info()[2]
लगता है कि मैं क्या करना चाहता हूँ, और मैं इसके साथ समस्याओं में कभी नहीं चला। लेकिन यह हैकिंग लगता है, न कि एक स्वीकृत अभ्यास। क्या कोई बेहतर तरीका है?
Exception
आपके मूल वर्ग के रूप में नहीं आते हैं - आप कुछ अधिक विशिष्ट उपवर्ग कर सकते हैं, और ऐसा करना चाहिए अगर यह समझ में आता है।
AppError
अपवाद का उपयोग करते हैं। एक अंतर्निहित त्रुटि का उपयोग करना बेहतर हो सकता है जैसेAttributeError
यह मत करो । नंगे
Exception
को उठाना बिल्कुल सही नहीं है; इसके बजाय हारून हॉल का शानदार जवाब देखें ।
इससे बहुत अधिक पायथोनिक नहीं मिल सकता है:
raise Exception("I know python!")
यदि आप अधिक जानकारी चाहते हैं, तो अजगर के लिए विवरण स्टेटमेंट देखें ।
पायथन 3 में रैसिंग अपवादों के लिए 4 अलग-अलग वाक्यविन्यास हैं:
1. raise exception
2. raise exception (args)
3. raise
4. raise exception (args) from original_exception
१. अपवाद छोड़ दो। २. अपवाद छोड़ दो (args)
यदि आप raise exception (args)
एक अपवाद को बढ़ाने के लिए उपयोग करते हैं तो args
जब आप अपवाद वस्तु को प्रिंट करते हैं तो प्रिंट किया जाएगा - जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है।
#raise exception (args)
try:
raise ValueError("I have raised an Exception")
except ValueError as exp:
print ("Error", exp) # Output -> Error I have raised an Exception
#raise execption
try:
raise ValueError
except ValueError as exp:
print ("Error", exp) # Output -> Error
3.raise
raise
बिना किसी तर्क के बयान अंतिम अपवाद को फिर से उठाता है। यह उपयोगी है अगर आपको अपवाद को पकड़ने के बाद कुछ क्रियाएं करने की आवश्यकता है और फिर इसे फिर से उठाना चाहते हैं। लेकिन अगर पहले कोई अपवाद नहीं था, तो raise
बयान TypeError
अपवाद को जन्म देता है ।
def somefunction():
print("some cleaning")
a=10
b=0
result=None
try:
result=a/b
print(result)
except Exception: #Output ->
somefunction() #some cleaning
raise #Traceback (most recent call last):
#File "python", line 8, in <module>
#ZeroDivisionError: division by zero
4. original_exception से अपवाद (args) उठाएं
इस कथन का उपयोग अपवाद के निर्माण में किया जाता है जिसमें एक अपवाद जो दूसरे अपवाद के जवाब में उठाया जाता है, उसमें मूल अपवाद का विवरण हो सकता है - जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है।
class MyCustomException(Exception):
pass
a=10
b=0
reuslt=None
try:
try:
result=a/b
except ZeroDivisionError as exp:
print("ZeroDivisionError -- ",exp)
raise MyCustomException("Zero Division ") from exp
except MyCustomException as exp:
print("MyException",exp)
print(exp.__cause__)
आउटपुट:
ZeroDivisionError -- division by zero
MyException Zero Division
division by zero
exception(args)
अधिक पसंद करता हैexception (args)
raise exception(args) from None
कहना है कि वर्तमान में सक्रिय अपवाद को संभाला गया था और अब कोई दिलचस्पी नहीं है। अन्यथा यदि आप एक except
ब्लॉक के अंदर अपवाद को उठाते हैं और इसे संभाला नहीं जाता है, तो दोनों अपवादों के लिए ट्रेसबैक को संदेश द्वारा अलग दिखाया जाएगा "उपरोक्त अपवाद से निपटने के दौरान, एक और अपवाद हुआ"
उस सामान्य मामले के लिए जहां आपको कुछ अप्रत्याशित परिस्थितियों के जवाब में एक अपवाद को फेंकने की आवश्यकता है, और यह कि आप कभी भी पकड़ने का इरादा नहीं रखते हैं, लेकिन बस तेजी से असफल होने के लिए आपको वहां से डिबग करने में सक्षम हो सकता है अगर यह कभी होता है - सबसे तार्किक एक लगता है AssertionError
:
if 0 < distance <= RADIUS:
#Do something.
elif RADIUS < distance:
#Do something.
else:
raise AssertionError("Unexpected value of 'distance'!", distance)
ValueError
है AssertionError
क्योंकि वहाँ एक दावे के साथ कोई समस्या नहीं है (क्योंकि कोई भी यहाँ नहीं बनाया जा रहा है) - समस्या एक मूल्य के साथ है। यदि आप वास्तव AssertionError
में इस मामले में चाहते हैं , तो लिखें assert distance > 0, 'Distance must be positive'
। लेकिन आपको इस तरह से त्रुटि की जांच नहीं करनी चाहिए क्योंकि दावे बंद किए जा सकते हैं ( python -O
)।
-O
।
पहले मौजूदा उत्तरों को पढ़ें, यह सिर्फ एक परिशिष्ट है।
ध्यान दें कि आप तर्कों के साथ या बिना अपवाद उठा सकते हैं।
उदाहरण:
raise SystemExit
कार्यक्रम से बाहर निकल जाता है, लेकिन आप जानना चाहते हैं कि क्या हुआ होगा। क्या आप इसका उपयोग कर सकते हैं।
raise SystemExit("program exited")
यह प्रोग्राम को बंद करने से पहले स्टोडर को "प्रोग्राम एक्साइटेड" प्रिंट करेगा।
raise SystemExit()
बेहतर विकल्प नहीं होगा ? पहले वाला भी काम क्यों करता है?
अपवाद फेंकने का एक और तरीका है assert
। आप एक शर्त को पूरा करने के लिए मुखर का उपयोग कर सकते हैं यदि पूरा किया जा रहा है तो वह नहीं उठाएगा AssertionError
। अधिक जानकारी के लिए एक नजर है यहाँ ।
def avg(marks):
assert len(marks) != 0,"List is empty."
return sum(marks)/len(marks)
mark2 = [55,88,78,90,79]
print("Average of mark2:",avg(mark2))
mark1 = []
print("Average of mark1:",avg(mark1))
बस ध्यान दें: कई बार जब आप सामान्य अपवादों को संभालना चाहते हैं। यदि आप फ़ाइलों का एक गुच्छा संसाधित कर रहे हैं और अपनी त्रुटियों को लॉग कर रहे हैं, तो आप किसी भी त्रुटि को पकड़ सकते हैं जो किसी फ़ाइल के लिए होती है, उसे लॉग इन करें, और शेष फ़ाइलों को संसाधित करना जारी रखें। उस मामले में, ए
try:
foo()
except Exception as e:
print(str(e)) # Print out handled error
इसे करने के लिए एक अच्छा तरीका ब्लॉक करें। आप अभी भी raise
विशिष्ट अपवाद चाहते हैं ताकि आप जान सकें कि उनका क्या मतलब है, हालांकि।
आपको उसके लिए अजगर का उठाना कथन सीखना चाहिए। इसे कोशिश ब्लॉक के अंदर रखा जाना चाहिए। उदाहरण -
try:
raise TypeError #remove TypeError by any other error if you want
except TypeError:
print('TypeError raised')
raise
वह है जो मुझे स्टैक ट्रेस को तोड़ने के बिना कोड निष्पादन के कई स्तरों पर कस्टम त्रुटि डिबगिंग करने में सक्षम होना चाहिए।