क्या मुझे हमेशा 'अपवाद' कथनों में अपवाद प्रकार निर्दिष्ट करना चाहिए?


93

जब PyCharm IDE का उपयोग except:बिना अपवाद के प्रकार का उपयोग करता है, तो IDE से एक अनुस्मारक ट्रिगर होता है जो यह अपवाद खंड है Too broad

क्या मुझे इस सलाह को अनदेखा करना चाहिए? या यह हमेशा अपवाद प्रकार विशिष्ट करने के लिए पायथोनिक है?


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

जवाबों:


89

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

उदाहरण के लिए, यदि आप किसी डेटाबेस में एक पंक्ति सम्मिलित कर रहे हैं, तो आप एक अपवाद को पकड़ना चाहते हैं जो इंगित करता है कि पंक्ति पहले से मौजूद है, इसलिए आप एक अद्यतन कर सकते हैं।

try:
    insert(connection, data)
except:
    update(connection, data)

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

एक मामला जहां आप नंगे except:का उपयोग करना चाहते हैं , वह एक प्रोग्राम के शीर्ष-स्तर पर है जिसे आपको नेटवर्क सर्वर की तरह हमेशा चलाने की आवश्यकता है। लेकिन फिर, आपको अपवादों को लॉग करने के लिए बहुत सावधान रहने की आवश्यकता है, अन्यथा यह गलत नहीं है कि क्या गलत हो रहा है। मूल रूप से, ऐसा करने वाले कार्यक्रम में केवल एक ही स्थान पर होना चाहिए।

इस सब के लिए एक कोरोलरी यह है कि आपका कोड कभी नहीं करना चाहिए raise Exception('some message')क्योंकि यह क्लाइंट कोड को उपयोग करने के लिए मजबूर करता है except:(या except Exception:जो लगभग उतना ही बुरा है)। आपको उस समस्या के अपवाद को परिभाषित करना चाहिए जिसे आप संकेत करना चाहते हैं (शायद कुछ अंतर्निहित अपवाद जैसे ValueErrorया उपवर्ग से विरासत में मिला है TypeError)। या आपको एक विशिष्ट अंतर्निहित अपवाद उठाना चाहिए। यह आपके कोड के उपयोगकर्ताओं को केवल उन अपवादों को पकड़ने में सावधान रहने में सक्षम बनाता है जिन्हें वे संभालना चाहते हैं।


7
+1 बहुत सही। उदाहरण के साथ और भी मजेदार: except:यह भी पकड़ता है (कई अन्य चीजों के बीच) NameErrorऔर AttributeError, इसलिए यदि आप tryब्लॉक में किसी चीज़ को मिस करते हैं (जैसे कि आपका "इंसर्ट" फ़ंक्शन वास्तव में कहा जाता है, insert_oneक्योंकि किसी ने स्थिरता को उतना महत्व नहीं दिया है), जितना उन्हें चाहिए हमेशा चुपचाप करने की कोशिश करता है update()

1
तो क्या होगा जब आपको यह सुनिश्चित करने की आवश्यकता होती है कि वर्तमान कॉल साइट के ऊपर एक अपवाद नहीं है? Ie - मैंने सभी विशिष्ट अपवादों को पकड़ लिया है जिन्हें मैं फेंक दिया जा सकता हूं, अब मुझे इसे जोड़ने की आवश्यकता है "अगर इस चीज को मैंने फेंका नहीं जाता है तो मुझे इसे चलाने से पहले इसे लॉग इन करने की आवश्यकता है" निष्पादन निष्पादन संदर्भ को मारता है "(जैसे कि main())?
एडम पार्किं

इस तरह की स्थिति मैं पैराग्राफ 'वन केस ...' के बारे में बात कर रहा हूं। यह निश्चित रूप से कभी-कभी आवश्यक होता है, लेकिन किसी भी दिए गए कार्यक्रम में वास्तव में केवल एक ही स्थान होना चाहिए जो ऐसा करता है। और आपको सावधान रहने की आवश्यकता है कि यह लॉग में स्पष्ट करता है कि क्या हो रहा है, अन्यथा आपके पास काम करने की कोशिश करने का निराशाजनक समय होगा कि आपका कार्यक्रम घटना / अनुरोध / जो भी सही ढंग से नहीं संभाल रहा है।
बबेरक्लंक

3
@ डेलन: इससे भी बदतर। except Exception:पकड़ लेंगे NameErrorऔर AttributeErrorभी। जो चीज नंगी except:होती है वह इतनी खराब होती है कि वह ऐसे सामान को पकड़ लेती है जिसका कोई व्यवसाय नहीं हो रहा है, उदाहरण के लिए SystemExit(जब आप कॉल करते हैं exitया उठाया जाता है sys.exit, और अब आपने एक इच्छित निकास को रोका है) और KeyboardInterrupt(फिर, यदि उपयोगकर्ता हिट करता है Ctrl-C, तो आप शायद नहीं चाहते हैं बस उन्हें चलाने के लिए)। केवल बाद वाला किसी भी वास्तविक अर्थ को पकड़ने के लिए बनाता है, और इसे स्पष्ट रूप से पकड़ा जाना चाहिए। कम से कम except Exception:उन दोनों को सामान्य रूप से प्रचारित करने देता है।
शैडो रेंजर

38

आपको उस सलाह की अनदेखी नहीं करनी चाहिए जो दुभाषिया आपको देता है।

से पीईपी-8 अजगर के लिए स्टाइल गाइड:

अपवादों को पकड़ते समय, किसी अपवाद को छोड़कर जब भी संभव हो, विशिष्ट अपवादों का उल्लेख करें: खंड।

उदाहरण के लिए, उपयोग करें:

 try:
     import platform_specific_module 
 except ImportError:
     platform_specific_module = None 

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

अंगूठे का एक अच्छा नियम दो मामलों को छोड़कर 'नंगे' के उपयोग को सीमित करना है:

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



9

यह पायथन के लिए विशिष्ट नहीं है।

अपवाद के पूरे बिंदु समस्या से निपटने के लिए है जहां यह संभव था।

तो आप कोड रखते हैं जो असाधारण cirumstances में समस्या को हल कर सकते हैं और एक दूसरे के लिए "अगला" संकल्प।

बात यह है कि आप उन सभी अपवादों को नहीं जान सकते जो कोड के एक टुकड़े द्वारा फेंके जा सकते हैं। आप सभी यह जान सकते हैं कि यदि यह एक कहावत है कि एक फ़ाइल अपवाद नहीं मिली, तो आप इसे फँसा सकते हैं और उपयोगकर्ता को उस कार्य को करने या रद्द करने के लिए प्रेरित कर सकते हैं।

अगर आप ट्रायल कैच राउंड लगाते हैं, तो इससे कोई फर्क नहीं पड़ता कि आपकी फाइल रूटीन में क्या समस्या थी (केवल रीड, परमिशन, यूएसी, वास्तव में एक पीडीएफ़ इत्यादि नहीं), हर एक आपकी फ़ाइल में ड्रॉप हो जाएगा जो कैच नहीं मिला, और आपका उपयोगकर्ता चिल्ला रहा है "लेकिन यह वहाँ है, यह कोड बकवास है"

अब कुछ ऐसे हालात हैं जहाँ आप सब कुछ झेल सकते हैं, लेकिन उन्हें सचेत रूप से चुना जाना चाहिए।

वे कुछ स्थानीय क्रियाओं (जैसे किसी संसाधन को बनाना या लॉक करना, उदाहरण के लिए लिखने के लिए डिस्क पर एक फ़ाइल खोलना) में पकड़ लेते हैं, फिर आप अपवाद को फिर से फेंकते हैं, जिससे उच्च स्तर पर निपटा जा सकता है)

दूसरी बात यह है कि आप यह नहीं सोचते कि यह गलत क्यों हुआ। उदाहरण के लिए मुद्रण। आपके पास पूरे दौर में एक पकड़ हो सकती है, यह कहने के लिए कि आपके प्रिंटर के साथ कुछ समस्या है, कृपया इसे सुलझाएं, और इसके कारण एप्लिकेशन को न मारें। ओना समान व्यर्थ यदि आपके कोड ने किसी प्रकार के शेड्यूल का उपयोग करके अलग-अलग कार्यों की एक श्रृंखला को निष्पादित किया है, तो आप चाहते हैं कि पूरी चीज मर जाएगी, क्योंकि कार्यों में से एक विफल हो गया।

नोट यदि आप ऊपर करते हैं, तो मैं कुछ प्रकार के अपवाद लॉगिंग की अनुशंसा नहीं कर सकता, उदाहरण के लिए, लॉग एंड को पकड़ने की कोशिश करें, अत्यधिक पर्याप्त।


मैं कहूंगा कि यह संतुलन के बारे में है। आपको जल्दी से अपवाद को पकड़ना होगा ताकि वह इससे उबर सके और यह जानने में देर हो सके कि इसके साथ कहां जाना है। यही कारण है कि जावा अपवाद हैंडलिंग इस तरह के कहर का कारण बनता है, क्योंकि आपको प्रत्येक चरण पर अपवाद को फिर से लपेटना होगा और आपको ढीली जानकारी देनी होगी।
ढिल

2
+1 के लिए "आपको परवाह नहीं है कि यह गलत क्यों हुआ।" मैं इसे कोड की एक पंक्ति के आसपास कई स्थानों पर उपयोग कर रहा हूं जहां मैं किसी URL से दिनांक / समय पार्स करता हूं। थर्ड पार्टी डेट / टाइम पार्सिंग लाइब्रेरी में उन सभी अपवादों की सूची नहीं है जो इसे फेंक सकते हैं (मैंने मानक ValueError के अलावा OverflowError और TypeError पाया है, लेकिन शायद अधिक हैं), और वैसे भी मुझे वास्तव में परवाह नहीं है कि क्यों एक अपवाद फेंक दिया गया था, मैं सिर्फ उपयोगकर्ता को यह कहते हुए एक उचित त्रुटि संदेश प्रदान करना चाहता हूं कि तारीख / समय के साथ कुछ गलत है।
माइकल रॉबी

3

आप इसके साथ कंट्रोल-सी भी पकड़ लेंगे, इसलिए इसे तब तक न करें जब तक आप इसे फिर से "फेंक" न दें। हालांकि, उस स्थिति में आपको "अंत में" का उपयोग करना चाहिए।


3

हमेशा की तरह, अपवाद के प्रकार का उल्लेख वहाँ कई प्रकार आप पकड़ नहीं करना चाहती, की तरह हैं SyntaxError, KeyboardInterrupt, MemoryErrorआदि


2
except Exception:उपरोक्त प्रकारों से बचने का उपयोग करने से जिन्हें हम पकड़ना नहीं चाहते हैं?
हॉर्सलओवरफ़ैट

except Exceptionठीक है।
उलरिच एकहार्ट

4
@ हॉर्सलओवरफ़ैट: except Exceptionकैच SyntaxErrorऔर MemoryErrorक्योंकि यह उनका बेस क्लास है। KeyboardInterrupt, SystemExit(द्वारा उठाए गए sys.exit()) पकड़े नहीं गए हैं (वे तत्काल आधारभूत उपवर्ग हैं)
jfs

ऐसा लगता है कि यह आदर्श नहीं है - और अधिक सटीक निर्दिष्ट करने के लिए बेहतर है।
हॉर्सलओवरफ़ैट

3

यहां वे स्थान हैं जहां मैं बिना किसी प्रकार को छोड़कर उपयोग करता हूं

  1. त्वरित और गंदा प्रोटोटाइप

अनियंत्रित अपवादों के लिए मेरे कोड में यह मुख्य उपयोग है

  1. शीर्ष स्तर मुख्य () फ़ंक्शन, जहां मैं हर अनकैप्ड अपवाद लॉग करता हूं

मैं हमेशा इसे जोड़ता हूं, ताकि उत्पादन कोड स्टैकट्रैक्स को फैल न सके

  1. आवेदन परतों के बीच

मेरे पास इसे करने के दो तरीके हैं:

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

मैं इसे इस तरह से पसंद करता हूं, मुझे यह पता लगाना आसान है कि किन अपवादों को उचित रूप से पकड़ा जाना चाहिए: निचले स्तर के अपवाद को उच्च स्तर से लॉग किए जाने पर समस्या को "बेहतर" देखता हूं।

  • इसे करने का दूसरा तरीका: निचले स्तर की परतों के प्रत्येक शीर्ष स्तर के कार्यों को एक सामान्य में लपेटे हुए कोड को छोड़कर, यह उस विशिष्ट परत पर सभी अखंडित अपवाद को पकड़ता है।

कुछ सहकर्मी इस तरह से पसंद करते हैं, क्योंकि यह निचले स्तर के कार्यों में निचले स्तर के अपवादों को रखता है, जहां वे "संबंधित" हैं।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.