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




exception exception-handling (4)

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

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

अपने संदेश में विशिष्ट रहें, उदाहरण के लिए:

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

सामान्य अपवाद मत बढ़ाओ

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

समस्या 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') 

इन तर्कों को अपवाद ऑब्जेक्ट पर तर्क विशेषता द्वारा एक्सेस किया जाता है। उदाहरण के लिए:

try:
    some_code_that_may_raise_our_value_error()
except ValueError as err:
    print(err.args)

प्रिंट

('message', 'foo', 'bar', 'baz')    

पायथन 2.5 में, उपयोगकर्ताओं को अपवादों को उपclass करने और तर्कों का उपयोग रोकने के लिए प्रोत्साहित करने के पक्ष में बेसएक्सप्शन में एक वास्तविक message विशेषता जोड़ा गया था, लेकिन message की शुरूआत और तर्कों के मूल बहिष्करण को वापस ले लिया गया है

सर्वोत्तम व्यवहार: खंड except

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

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() ) के साथ stacktrace (और त्रुटि मान) को संरक्षित कर सकते हैं, लेकिन यह तरीका अधिक त्रुटि प्रवण है और इसमें पाइथन 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]

यदि आप चाहते हैं, तो आप संशोधित कर सकते हैं कि आपके नए raise के साथ क्या होता है - उदाहरण के लिए नए तर्क सेट करना:

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.

सभी आधुनिक संस्करणों में, यह वास्तव में टाइपएरर बढ़ाएगा, क्योंकि आप बेसएक्सप्शन प्रकार नहीं बढ़ा रहे हैं। यदि आप सही अपवाद की जांच नहीं कर रहे हैं और ऐसे समीक्षक नहीं हैं जो इस मुद्दे से अवगत हैं, तो यह उत्पादन में हो सकता है।

उदाहरण उपयोग

मैं अपने एपीआई के उपभोक्ताओं को चेतावनी देने के लिए अपवाद उठाता हूं यदि वे गलत तरीके से इसका उपयोग कर रहे हैं:

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:

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

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


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

इससे ज्यादा पाइथनिक नहीं मिल सकता है:

raise Exception("I know python!")

यदि आप अधिक जानकारी चाहते हैं तो पाइथन के लिए raise कथन दस्तावेज़ देखें।


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

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

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

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

उदाहरण:

raise SystemExit

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

raise SystemExit("program exited")

यह प्रोग्राम बंद करने से पहले "प्रोग्राम बाहर निकला" मुद्रित करेगा।





exception-handling