पायथन में एक अपवाद को मैन्युअल रूप से उठाना (फेंकना)


2261

मैं पायथन में अपवाद कैसे उठा सकता हूं ताकि बाद में इसे एक exceptब्लॉक के माध्यम से पकड़ा जा सके ?

जवाबों:


2934

मैं पायथन में अपवाद को मैन्युअल रूप से कैसे फेंक / बढ़ा सकता हूं?

सबसे विशिष्ट अपवाद निर्माणकर्ता का उपयोग करें जो आपके मुद्दे को शब्दार्थ रूप से फिट करता है

अपने संदेश में विशिष्ट बनें, जैसे:

raise ValueError('A very specific bad thing happened.')

सामान्य अपवाद न बढ़ाएँ

जेनरिक उठाने से बचें Exception। इसे पकड़ने के लिए, आपको अन्य सभी विशिष्ट अपवादों को पकड़ना होगा जो इसे उप-वर्ग बनाते हैं।

समस्या 1: बग्स को छिपाना

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',)

समस्या 2: पकड़ में नहीं आएगी

और अधिक विशिष्ट कैच सामान्य अपवाद को नहीं पकड़ेंगे:

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 की मूल पदावनति की शुरूआत को हटा दिया गया थाBaseExceptionargsmessage

सर्वोत्तम प्रथाएँ: 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, अपवाद जंजीर

पायथन 3 में, आप अपवादों को श्रृंखलाबद्ध कर सकते हैं, जो ट्रेसबैक को संरक्षित करते हैं:

    raise RuntimeError('specific message') from error

जागरूक रहें:

  • इस करता बदलते त्रुटि प्रकार उठाया अनुमति देते हैं, और
  • यह पायथन 2 के साथ संगत नहीं है

पदावनत विधि:

ये आसानी से छिप सकते हैं और उत्पादन कोड में भी जा सकते हैं। आप एक अपवाद उठाना चाहते हैं, और उन्हें करने से एक अपवाद बढ़ जाएगा, लेकिन ऐसा कोई इरादा नहीं है!

पायथन 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)))

Apropos जब अपनी खुद की त्रुटि प्रकार बनाएँ

"मैं उद्देश्य पर एक त्रुटि बनाना चाहता हूं, ताकि यह अपवाद में जाए"

आप अपनी स्वयं की त्रुटि प्रकार बना सकते हैं, यदि आप यह बताना चाहते हैं कि कुछ विशिष्ट आपके आवेदन के साथ गलत है, बस अपवाद पदानुक्रम में उपयुक्त बिंदु को उप-वर्गित करें:

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.')

19
इसके लिए धन्यवाद, यह वही है जो मुझे चाहिए था। नंगे raiseवह है जो मुझे स्टैक ट्रेस को तोड़ने के बिना कोड निष्पादन के कई स्तरों पर कस्टम त्रुटि डिबगिंग करने में सक्षम होना चाहिए।
कैफीन

यह एक बेहतरीन जवाब है। लेकिन मैं अभी भी बहुत सारे 2.7 कोड के साथ काम करता हूं, और मैं अक्सर खुद को एक अप्रत्याशित अपवाद की जानकारी जोड़ना चाहता हूं, जैसे कि इनपुट फ़ाइल की स्थिति या कुछ चर के मान, लेकिन मूल स्टैक और अपवाद को रखें। मैं इसे लॉग कर सकता हूं, लेकिन कभी-कभी मैं इसे लॉग इन नहीं करना चाहता, उदाहरण के लिए यदि मूल कोड अंततः इसे संभालता है। raise sys.exc_info()[0], (sys.exc_info()[1], my_extra_info), sys.exc_info()[2]लगता है कि मैं क्या करना चाहता हूँ, और मैं इसके साथ समस्याओं में कभी नहीं चला। लेकिन यह हैकिंग लगता है, न कि एक स्वीकृत अभ्यास। क्या कोई बेहतर तरीका है?
माइकल शेपर

2
@brennanyoung उस संदर्भ में मुझे लगता है कि यह एक वाक्यविन्यास को बढ़ाने के लिए भ्रामक हो सकता है - शायद आपको एक कस्टम अपवाद उठाना चाहिए। : मैं कैसे यहाँ समझाओ stackoverflow.com/a/26938914/541136
हारून हॉल

2
ध्यान दें कि पूर्ण उद्धरण है "सभी अंतर्निहित, गैर-सिस्टम-एक्साइटिंग अपवाद इस वर्ग से प्राप्त किए गए हैं। सभी उपयोगकर्ता-परिभाषित अपवाद भी इसी वर्ग से प्राप्त किए जाने चाहिए।" - इसका मतलब यह है कि आपको उन 4 अपवादों में से एक का उपयोग नहीं करना चाहिए जो Exceptionआपके मूल वर्ग के रूप में नहीं आते हैं - आप कुछ अधिक विशिष्ट उपवर्ग कर सकते हैं, और ऐसा करना चाहिए अगर यह समझ में आता है।
आरोन हॉल

1
" सर्वोत्तम प्रथाओं: खंड को छोड़कर " के उदाहरण में , आप एक अपरिभाषित AppErrorअपवाद का उपयोग करते हैं। एक अंतर्निहित त्रुटि का उपयोग करना बेहतर हो सकता है जैसेAttributeError
स्टीवोइसक

530

यह मत करो । नंगे Exceptionको उठाना बिल्कुल सही नहीं है; इसके बजाय हारून हॉल का शानदार जवाब देखें ।

इससे बहुत अधिक पायथोनिक नहीं मिल सकता है:

raise Exception("I know python!")

यदि आप अधिक जानकारी चाहते हैं, तो अजगर के लिए विवरण स्टेटमेंट देखें ।


67
कृपया नहीं! यह आपके द्वारा पकड़े जाने के बारे में विशिष्ट होने की क्षमता को हटा देता है। यह गलत तरीके से इसे करने का तरीका है। इस एक के बजाय हारून हॉल के उत्कृष्ट उत्तर पर एक नज़र डालें। यह ऐसा समय है जब मैं चाहता हूं कि मैं प्रति उत्तर एक से अधिक डाउनवोट दे सकूं।
दाऊद इब्न करीम

27
@PeterR यह उतना ही भयानक है कि इसमें बहुत कम डाउनवोट हैं। किसी को भी इस जवाब को पढ़ने के लिए, कभी भी यह मत करो! सही उत्तर हारून हॉल का है।
दाऊद इब्न करीम

6
मुझे लगता है कि इस बारे में अधिक विस्तृत स्पष्टीकरण होना चाहिए कि यह गलत या इतना बुरा क्यों है।
चार्ली पार्कर

9
@CharlieParker है। यह हारून हॉल के जवाब का पहला हिस्सा है ।
दीनी

5
इस उत्तर को विलोपन के लिए क्यों नहीं ध्वजांकित किया जा सकता है? इसे पहले ही 93 डाउनवोट मिल चुके हैं!
codeforester

54

पायथन 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

7
कृपया ध्यान दें कि PEP8 exception(args)अधिक पसंद करता हैexception (args)
Gloweye

यह भी raise exception(args) from Noneकहना है कि वर्तमान में सक्रिय अपवाद को संभाला गया था और अब कोई दिलचस्पी नहीं है। अन्यथा यदि आप एक exceptब्लॉक के अंदर अपवाद को उठाते हैं और इसे संभाला नहीं जाता है, तो दोनों अपवादों के लिए ट्रेसबैक को संदेश द्वारा अलग दिखाया जाएगा "उपरोक्त अपवाद से निपटने के दौरान, एक और अपवाद हुआ"
cg909

35

उस सामान्य मामले के लिए जहां आपको कुछ अप्रत्याशित परिस्थितियों के जवाब में एक अपवाद को फेंकने की आवश्यकता है, और यह कि आप कभी भी पकड़ने का इरादा नहीं रखते हैं, लेकिन बस तेजी से असफल होने के लिए आपको वहां से डिबग करने में सक्षम हो सकता है अगर यह कभी होता है - सबसे तार्किक एक लगता है AssertionError:

if 0 < distance <= RADIUS:
    #Do something.
elif RADIUS < distance:
    #Do something.
else:
    raise AssertionError("Unexpected value of 'distance'!", distance)

19
के लिए यह एक बेहतर मामला ValueErrorहै AssertionErrorक्योंकि वहाँ एक दावे के साथ कोई समस्या नहीं है (क्योंकि कोई भी यहाँ नहीं बनाया जा रहा है) - समस्या एक मूल्य के साथ है। यदि आप वास्तव AssertionErrorमें इस मामले में चाहते हैं , तो लिखें assert distance > 0, 'Distance must be positive'। लेकिन आपको इस तरह से त्रुटि की जांच नहीं करनी चाहिए क्योंकि दावे बंद किए जा सकते हैं ( python -O)।
दो-बिट अल्केमिस्ट

1
@ टू-बिटअल्केमिस्ट गुड पॉइंट। विचार सरलता में खो गया था, जब मैंने ऊपर सरल उदाहरण लिखा था। इसी तरह के कई मामलों में यह एक ऐसी स्थिति है जो किसी विशेष मूल्य से जुड़ी नहीं है। बल्कि अर्थ यह है कि "नियंत्रण प्रवाह कभी भी यहां नहीं होना चाहिए"।
एवगेनी सर्गेव

2
@ दो-बिटकेमिस्ट दावे को बंद किया जा सकता है, हां, लेकिन फिर आपको उन्हें त्रुटि जांच में उपयोग नहीं करना चाहिए?
एवगेनी सर्गेव

अच्छा वह निर्भर करता है। मुझे लगता है कि वितरित करने के लिए एक कार्यक्रम में मेरी केवल त्रुटि की जाँच नहीं होने देंगे। दूसरी ओर, मैं सिर्फ अपने सहकर्मियों के लिए एक कार्यक्रम बना सकता था और उन्हें बता सकता था कि अगर वे इसे चलाते हैं तो वे अपने जोखिम पर इसका इस्तेमाल करते हैं -O
दो-बिट अल्केमिस्ट

1
@ दो-बिटअल्केमिस्ट मेरे लिए मुखर की भूमिका प्रति-त्रुटि त्रुटि-जाँच नहीं है (जो कि परीक्षण के लिए है), लेकिन वे कोड के भीतर बाड़ सेट करते हैं जो कुछ बग के माध्यम से प्राप्त नहीं कर सकते हैं। इसलिए बग को ट्रैक करना और अलग करना आसान हो जाता है, जो अनिवार्य रूप से होगा। यह सिर्फ अच्छी आदतें हैं जो थोड़ा प्रयास करती हैं, जबकि परीक्षण में बहुत प्रयास और बहुत समय लगता है।
इवगेनी सर्गेव

12

पहले मौजूदा उत्तरों को पढ़ें, यह सिर्फ एक परिशिष्ट है।

ध्यान दें कि आप तर्कों के साथ या बिना अपवाद उठा सकते हैं।

उदाहरण:

raise SystemExit

कार्यक्रम से बाहर निकल जाता है, लेकिन आप जानना चाहते हैं कि क्या हुआ होगा। क्या आप इसका उपयोग कर सकते हैं।

raise SystemExit("program exited")

यह प्रोग्राम को बंद करने से पहले स्टोडर को "प्रोग्राम एक्साइटेड" प्रिंट करेगा।


2
क्या यह ओओपी प्रतिमान के खिलाफ नहीं है? मुझे लगता है, पहला मामला कक्षा संदर्भ और दूसरा SystemExit का एक उदाहरण है। raise SystemExit()बेहतर विकल्प नहीं होगा ? पहले वाला भी काम क्यों करता है?
बर्न

2

अपवाद फेंकने का एक और तरीका है 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))

2

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

try:
    foo() 
except Exception as e:
    print(str(e)) # Print out handled error

इसे करने के लिए एक अच्छा तरीका ब्लॉक करें। आप अभी भी raiseविशिष्ट अपवाद चाहते हैं ताकि आप जान सकें कि उनका क्या मतलब है, हालांकि।


0

आपको उसके लिए अजगर का उठाना कथन सीखना चाहिए। इसे कोशिश ब्लॉक के अंदर रखा जाना चाहिए। उदाहरण -

try:
    raise TypeError            #remove TypeError by any other error if you want
except TypeError:
    print('TypeError raised')
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.