जैसा कि आपने सही अनुमान लगाया है, इसके दो पहलू हैं: किसी भी प्रकार के अपवाद को निर्दिष्ट करके किसी भी त्रुटि को पकड़ना except, और बिना किसी कार्रवाई के बस इसे पारित करना।
मेरी व्याख्या "थोड़ी" लंबी है - इतना tl; ड्र इसे नीचे तक तोड़ता है:
- कोई त्रुटि न पकड़ें । हमेशा निर्दिष्ट करें कि आप किन अपवादों से उबरने के लिए तैयार हैं और केवल उन्हीं को पकड़ते हैं।
- ब्लॉकों को छोड़कर गुजरने से बचने की कोशिश करें । जब तक स्पष्ट रूप से वांछित नहीं है, यह आमतौर पर एक अच्छा संकेत नहीं है।
लेकिन विस्तार से जाने:
कोई त्रुटि न पकड़ें
एक tryब्लॉक का उपयोग करते समय , आप आमतौर पर ऐसा करते हैं क्योंकि आप जानते हैं कि अपवाद को फेंकने का एक मौका है। इस प्रकार, आपके पास पहले से ही एक अनुमानित विचार है कि क्या टूट सकता है और किस अपवाद को फेंका जा सकता है। ऐसे मामलों में, आप एक अपवाद को पकड़ते हैं क्योंकि आप इससे सकारात्मक रूप से उबर सकते हैं । इसका मतलब है कि आप अपवाद के लिए तैयार हैं और कुछ वैकल्पिक योजना है जो आप उस अपवाद के मामले में अपनाएंगे।
उदाहरण के लिए, जब आप किसी नंबर को इनपुट करने के लिए उपयोगकर्ता से पूछते हैं, तो आप इनपुट का उपयोग करके कन्वर्ट कर सकते हैं, int()जो कि बढ़ा सकता है ValueError। आप आसानी से ठीक कर सकते हैं कि उपयोगकर्ता को इसे फिर से आज़माने के लिए कह सकते हैं, इसलिए उपयोगकर्ता को फिर से पकड़ना ValueErrorऔर फिर से संकेत देना एक उचित योजना होगी। एक अलग उदाहरण होगा यदि आप किसी फ़ाइल से कुछ कॉन्फ़िगरेशन पढ़ना चाहते हैं, और वह फ़ाइल मौजूद नहीं है। चूँकि यह एक कॉन्फ़िगरेशन फ़ाइल है, इसलिए हो सकता है कि आपके पास कुछ डिफ़ॉल्ट कॉन्फ़िगरेशन एक कमबैक के रूप में हो, इसलिए फ़ाइल बिल्कुल आवश्यक नहीं है। तो एक को पकड़ने FileNotFoundErrorऔर बस डिफ़ॉल्ट विन्यास आवेदन यहाँ एक अच्छी योजना होगी। अब इन दोनों मामलों में, हमारे पास एक बहुत ही विशिष्ट अपवाद है जिसकी हम अपेक्षा करते हैं और इससे उबरने के लिए समान रूप से विशिष्ट योजना है। जैसे, प्रत्येक मामले में, हम स्पष्ट रूप से केवल इतना ही except निश्चित करते हैं अपवाद।
हालाँकि, अगर हमें सब कुछ पकड़ना था , तो — उन अपवादों के अलावा, जिनसे हम उबरने के लिए तैयार हैं — एक मौका यह भी है कि हमें ऐसे अपवाद मिलते हैं, जिनकी हमें उम्मीद नहीं थी, और जिनसे हम वास्तव में उबर नहीं सकते; से उबरना चाहिए या नहीं।
चलो ऊपर से कॉन्फ़िगरेशन फ़ाइल का उदाहरण लेते हैं। एक गुम फ़ाइल के मामले में, हमने अभी अपना डिफ़ॉल्ट कॉन्फ़िगरेशन लागू किया है, और बाद में कॉन्फ़िगरेशन को स्वचालित रूप से सहेजने के लिए बाद में निर्णय लिया जा सकता है (इसलिए अगली बार, फ़ाइल मौजूद है)। अब कल्पना कीजिए कि हमें ए IsADirectoryError, या ए मिलता हैPermissionErrorबजाय। ऐसे मामलों में, हम संभवतः जारी नहीं रखना चाहते हैं; हम अभी भी अपना डिफ़ॉल्ट कॉन्फ़िगरेशन लागू कर सकते हैं, लेकिन हम बाद में फ़ाइल को सहेज नहीं पाएंगे। और यह संभावना है कि उपयोगकर्ता का मतलब कस्टम कॉन्फ़िगरेशन भी है, इसलिए डिफ़ॉल्ट मानों का उपयोग करना संभव नहीं है। इसलिए हम उपयोगकर्ता को इसके बारे में तुरंत बताना चाहते हैं, और शायद कार्यक्रम के निष्पादन को भी समाप्त कर सकते हैं। लेकिन ऐसा कुछ नहीं है जिसे हम कुछ छोटे कोड वाले हिस्से में कहीं गहरे में करना चाहते हैं; यह अनुप्रयोग-स्तर के महत्व का कुछ है, इसलिए इसे शीर्ष पर संभाला जाना चाहिए - इसलिए अपवाद को छोड़ दें।
पायथन 2 मुहावरों के दस्तावेज़ में एक और सरल उदाहरण भी वर्णित है । यहां, कोड में एक सरल टाइपो मौजूद है जो इसे तोड़ने का कारण बनता है। क्योंकि हम हर अपवाद को पकड़ रहे हैं , हम भी NameErrors और SyntaxErrors को पकड़ते हैं । दोनों गलतियाँ हैं जो प्रोग्रामिंग करते समय हम सभी के साथ होती हैं; और दोनों गलतियाँ हैं हम कोड को शिपिंग करते समय बिल्कुल शामिल नहीं करना चाहते हैं। लेकिन क्योंकि हमने भी उन लोगों को पकड़ा था, हम यह भी नहीं जान पाएंगे कि वे वहां हुए थे और इसे सही ढंग से डिबग करने के लिए कोई भी मदद खो देते हैं।
लेकिन और भी खतरनाक अपवाद हैं जिनके लिए हम तैयार नहीं हैं। उदाहरण के लिए SystemError आमतौर पर कुछ ऐसा होता है जो शायद ही कभी होता है और जिसके लिए हम वास्तव में योजना नहीं बना सकते हैं; इसका मतलब है कि कुछ और जटिल चल रहा है, ऐसा कुछ जो हमें वर्तमान कार्य को जारी रखने से रोकता है।
किसी भी मामले में, यह बहुत कम संभावना नहीं है कि आप कोड के एक छोटे से हिस्से में सब कुछ के लिए तैयार हैं, इसलिए वास्तव में आपको केवल उन अपवादों को पकड़ना चाहिए जिनके लिए आप तैयार हैं। कुछ लोग कम से कम पकड़ने का सुझाव देते हैं Exceptionक्योंकि इसमें ऐसी चीजें शामिल नहीं होंगी जैसे SystemExitऔर KeyboardInterruptजो डिजाइन द्वारा आपके आवेदन को समाप्त करने के लिए हैं, लेकिन मैं तर्क दूंगा कि यह अभी भी बहुत ही अनिर्दिष्ट है। केवल एक ही जगह है जहां मैं व्यक्तिगत रूप से कैच Exceptionया सिर्फ किसी को स्वीकार करता हूंअपवाद, और यह एक एकल वैश्विक अनुप्रयोग-स्तरीय अपवाद हैंडलर में है, जिसका कोई भी उद्देश्य नहीं है कि हम उस अपवाद को लॉग इन करें जिसके लिए हम तैयार नहीं थे। इस तरह, हम अभी भी अप्रत्याशित अपवादों के बारे में अधिक जानकारी रख सकते हैं, जिसका उपयोग हम अपने कोड को विस्तारित करने के लिए कर सकते हैं ताकि वे स्पष्ट रूप से संभाल सकें (यदि हम उनसे उबर सकते हैं) या - बग के मामले में - परीक्षण के मामले बनाने के लिए सुनिश्चित करें ऐसा फिर नहीं होगा। लेकिन निश्चित रूप से, यह केवल तभी काम करता है जब हम केवल उन अपवादों को पकड़ते हैं जो हम पहले से ही उम्मीद कर रहे थे, इसलिए जिन लोगों से हम उम्मीद नहीं करते थे वे स्वाभाविक रूप से बबल अप करेंगे।
ब्लॉकों को छोड़कर गुजरने से बचने की कोशिश करें
जब स्पष्ट रूप से विशिष्ट अपवादों के एक छोटे से चयन को पकड़ा जाता है, तो कई परिस्थितियां होती हैं जिनमें हम बस कुछ नहीं करने से ठीक हो जाएंगे। ऐसे मामलों में, except SomeSpecificException: passबस ठीक है। हालांकि अधिकांश समय, यह मामला नहीं है क्योंकि हमें पुनर्प्राप्ति प्रक्रिया से संबंधित कुछ कोड की आवश्यकता है (जैसा कि ऊपर उल्लेख किया गया है)। यह उदाहरण के लिए कुछ हो सकता है जो फिर से कार्रवाई को पुनः प्राप्त करता है, या इसके बजाय एक डिफ़ॉल्ट मान सेट करने के लिए।
यदि ऐसा नहीं है, उदाहरण के लिए, क्योंकि हमारे कोड को पहले से ही दोहराया जाता है जब तक कि यह सफल नहीं हो जाता है, तो बस पासिंग काफी अच्छी है। ऊपर से हमारे उदाहरण को लेते हुए, हम उपयोगकर्ता को एक नंबर दर्ज करने के लिए कहना चाहते हैं। क्योंकि हम जानते हैं कि उपयोगकर्ता ऐसा करना पसंद नहीं करते हैं, जो हम उनसे माँगते हैं, इसलिए हम इसे पहली बार एक लूप में डाल सकते हैं, इसलिए यह इस तरह दिख सकता है:
def askForNumber ():
while True:
try:
return int(input('Please enter a number: '))
except ValueError:
pass
क्योंकि हम तब तक कोशिश करते रहते हैं जब तक कि कोई अपवाद नहीं फेंक दिया जाता है, हमें ब्लॉक को छोड़कर कुछ विशेष करने की आवश्यकता नहीं है, इसलिए यह ठीक है। लेकिन निश्चित रूप से, कोई यह तर्क दे सकता है कि हम कम से कम उपयोगकर्ता को यह बताने के लिए कुछ त्रुटि संदेश दिखाना चाहते हैं कि उसे इनपुट क्यों दोहराना है।
हालांकि कई अन्य मामलों में, केवल एक में गुजरना exceptएक संकेत है कि हम वास्तव में उस अपवाद के लिए तैयार नहीं थे जिसे हम पकड़ रहे हैं। जब तक कि वे अपवाद सरल (जैसे ValueErrorया TypeError) नहीं हैं, और जिस कारण से हम गुजर सकते हैं वह स्पष्ट है, बस गुजरने से बचने की कोशिश करें। अगर वास्तव में कुछ नहीं करना है (और आप इसके बारे में पूरी तरह से निश्चित हैं), तो एक टिप्पणी जोड़ने पर विचार करें कि ऐसा क्यों है; अन्यथा, वास्तव में कुछ रिकवरी कोड को छोड़कर ब्लॉक का विस्तार करें।
except: pass
सबसे खराब अपराधी हालांकि दोनों का संयोजन है। इसका मतलब है कि हम स्वेच्छा से किसी भी त्रुटि को पकड़ रहे हैं, हालांकि हम इसके लिए बिल्कुल तैयार नहीं हैं और हम इसके बारे में कुछ भी नहीं करते हैं। आप कम से कम त्रुटि को लॉग इन करना चाहते हैं और यह भी संभावना है कि यह अभी भी आवेदन को समाप्त करने के लिए इसे reraise (यह संभावना नहीं है कि आप मेमोरी के बाद सामान्य की तरह जारी रख सकते हैं)। हालांकि पास होने पर न केवल एप्लिकेशन को कुछ हद तक जीवित रखा जा सकता है (जहां आप पाठ्यक्रम को पकड़ते हैं), बल्कि सभी जानकारी को भी फेंक देते हैं, जिससे त्रुटि का पता लगाना असंभव हो जाता है - जो विशेष रूप से सच है यदि आप इसे खोज नहीं रहे हैं।
तो नीचे की रेखा है: केवल उन अपवादों को पकड़ो जिनकी आप वास्तव में अपेक्षा करते हैं और जिनसे उबरने के लिए तैयार हैं; अन्य सभी की संभावना है कि या तो गलतियाँ आप ठीक करें, या कुछ भी आप के लिए तैयार नहीं हैं। पासिंग विशिष्ट अपवाद ठीक यदि आप वास्तव में उनके बारे में कुछ करने की ज़रूरत नहीं है। अन्य सभी मामलों में, यह सिर्फ अनुमान लगाने और आलसी होने का संकेत है। और आप निश्चित रूप से इसे ठीक करना चाहते हैं।
loggingउत्पादन में स्ट्रीमिंग से बचने के लिए DEBUG स्तर पर मॉड्यूल का उपयोग करें , लेकिन उन्हें विकास में उपलब्ध रखें।