एक खराब प्रोग्रामिंग प्रैक्टिस को "छोड़कर: पास" क्यों किया जाता है?


324

मैं अक्सर अन्य स्टैक ओवरफ्लो प्रश्नों पर टिप्पणियों को देखता हूं कि कैसे उपयोग except: passको हतोत्साहित किया जाता है। यह बुरा क्यों है? कभी-कभी मुझे परवाह नहीं है कि क्या त्रुटियां हैं, और मैं कोड के साथ जारी रखना चाहता हूं।

try:
    something
except:
    pass

क्यों एक except: passब्लॉक बुरा उपयोग कर रहा है? क्या यह बुरा है? क्या यह तथ्य है passकि मैं exceptकिसी त्रुटि पर हूं या मेरी कोई त्रुटि है?


1
यह बहुत कम से कम, मैं आपको लॉग इन करने का सुझाव दूंगा, इसलिए आप जानते हैं कि आप किन समस्याओं की अनदेखी कर रहे हैं। loggingउत्पादन में स्ट्रीमिंग से बचने के लिए DEBUG स्तर पर मॉड्यूल का उपयोग करें , लेकिन उन्हें विकास में उपलब्ध रखें।
पीसीयूरी

जवाबों:


346

जैसा कि आपने सही अनुमान लगाया है, इसके दो पहलू हैं: किसी भी प्रकार के अपवाद को निर्दिष्ट करके किसी भी त्रुटि को पकड़ना except, और बिना किसी कार्रवाई के बस इसे पारित करना।

मेरी व्याख्या "थोड़ी" लंबी है - इतना tl; ड्र इसे नीचे तक तोड़ता है:

  1. कोई त्रुटि न पकड़ें । हमेशा निर्दिष्ट करें कि आप किन अपवादों से उबरने के लिए तैयार हैं और केवल उन्हीं को पकड़ते हैं।
  2. ब्लॉकों को छोड़कर गुजरने से बचने की कोशिश करें । जब तक स्पष्ट रूप से वांछित नहीं है, यह आमतौर पर एक अच्छा संकेत नहीं है।

लेकिन विस्तार से जाने:

कोई त्रुटि न पकड़ें

एक 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 (यह संभावना नहीं है कि आप मेमोरी के बाद सामान्य की तरह जारी रख सकते हैं)। हालांकि पास होने पर न केवल एप्लिकेशन को कुछ हद तक जीवित रखा जा सकता है (जहां आप पाठ्यक्रम को पकड़ते हैं), बल्कि सभी जानकारी को भी फेंक देते हैं, जिससे त्रुटि का पता लगाना असंभव हो जाता है - जो विशेष रूप से सच है यदि आप इसे खोज नहीं रहे हैं।


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


1
"आप कम से कम त्रुटि को लॉग इन करना चाहते हैं और यह भी संभावना है कि यह अभी भी एप्लिकेशन को समाप्त कर सकता है"। क्या आप यह प्रदर्शित कर सकते हैं कि इसे अपवाद के रूप में "reraise" कैसे करें, इसे पकड़ने के बाद भी बुदबुदाते रहने दें? यह मुझे कुछ कस्टम त्रुटि संदेशों में जोड़ने के लिए उपयोगी लगता है, जबकि अभी भी अपवाद को छोड़ने के लिए आवेदन को मजबूर करता है।
गेब्रियल स्टेपल्स

1
यह स्पष्ट करने में मदद करता है: वे कंबल का उपयोग करते हैं except, लेकिन फिर raiseआवेदन को समाप्त करते हुए अपवाद बुलबुले को जारी रखने के लिए कोई तर्क नहीं देते हैं। मुझे यह पसंद है: ianbicking.org/blog/2007/09/re-raising-exception.html । कंबल का उपयोग नहीं करने के बारे में नियम के लिए एक ठोस अपवाद जैसा दिखता है except
गेब्रियल स्टेपल्स

1
@GabrielStaples हाँ, एक पकड़े गए अपवाद का उपयोग करके पुनर्विचार किया जा सकता है raise। आप आमतौर पर केवल अपवाद लॉग करने के लिए अपने आवेदन के भीतर कुछ स्थानों में ऐसा करेंगे।
प्रहार

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

262

यहां मुख्य समस्या यह है कि यह सभी और किसी भी त्रुटि को अनदेखा करता है: मेमोरी से बाहर, सीपीयू जल रहा है, उपयोगकर्ता बंद करना चाहता है, प्रोग्राम बाहर निकलना चाहता है, Jabberwocky उपयोगकर्ताओं को मार रहा है।

यह रास्ता बहुत ज्यादा है। आपके सिर में, आप सोच रहे हैं "मैं इस नेटवर्क त्रुटि को अनदेखा करना चाहता हूं"। यदि कुछ अनपेक्षित हो जाता है, तो आपका कोड चुपचाप जारी रहता है और पूरी तरह से अप्रत्याशित तरीके से टूट जाता है जिसे कोई भी डिबग नहीं कर सकता है।

इसलिए आपको विशेष रूप से केवल कुछ त्रुटियों को अनदेखा करने के लिए खुद को सीमित करना चाहिए और बाकी को पास होने देना चाहिए।


75

अपने छद्म कोड का शाब्दिक अर्थ निकालना भी कोई त्रुटि नहीं देता है:

try:
    something
except:
    pass

जैसे कि यह कोड को फेंकने के बजाय पूरी तरह से मान्य टुकड़ा है NameError। मुझे आशा है कि यह वह नहीं है जो आप चाहते हैं।


51

एक खराब प्रोग्रामिंग प्रैक्टिस को "छोड़कर: पास" क्यों किया जाता है?

यह बुरा क्यों है?

try:
    something
except:
    pass

यह हर संभव अपवाद को पकड़ता है, जिसमें शामिल हैं GeneratorExit, KeyboardInterruptऔर SystemExit- जो अपवाद हैं जिन्हें आप शायद पकड़ने का इरादा नहीं रखते हैं। यह पकड़ने जैसा ही है BaseException

try:
    something
except BaseException:
    pass

दस्तावेज़ के पुराने संस्करण कहते हैं :

चूंकि पायथन में हर त्रुटि एक अपवाद को जन्म देती है, इसलिए except:कई प्रोग्रामिंग त्रुटियों का उपयोग रनटाइम समस्याओं की तरह हो सकता है, जो डिबगिंग प्रक्रिया में बाधा उत्पन्न करता है।

पायथन एक्सेप्शन पदानुक्रम

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

यहाँ पायथन 3 अपवाद पदानुक्रम है - क्या आप वास्तव में उन्हें सभी को पकड़ना चाहते हैं ?:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
           +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

यह मत करो

यदि आप अपवाद हैंडलिंग के इस रूप का उपयोग कर रहे हैं:

try:
    something
except: # don't just do a bare except!
    pass

तब आप अपने somethingब्लॉक को Ctrl-C के साथ बाधित नहीं कर पाएंगे । आपका प्रोग्राम tryकोड ब्लॉक के अंदर हर संभव अपवाद को देख लेगा ।

यहां एक और उदाहरण दिया गया है जिसमें समान अवांछनीय व्यवहार होगा:

except BaseException as e: # don't do this either - same as bare!
    logging.info(e)

इसके बजाय, केवल उस विशिष्ट अपवाद को पकड़ने का प्रयास करें जिसे आप जानते हैं कि आप खोज रहे हैं। उदाहरण के लिए, यदि आप जानते हैं कि आपको रूपांतरण पर मूल्य-त्रुटि मिल सकती है:

try:
    foo = operation_that_includes_int(foo)
except ValueError as e:
    if fatal_condition(): # You can raise the exception if it's bad,
        logging.info(e)   # but if it's fatal every time,
        raise             # you probably should just not catch it.
    else:                 # Only catch exceptions you are prepared to handle.
        foo = 0           # Here we simply assign foo to 0 and continue. 

एक अन्य उदाहरण के साथ आगे की व्याख्या

हो सकता है कि आप ऐसा कर रहे हों क्योंकि आप वेब-स्क्रैपिंग कर रहे हैं और कह रहे हैं, एक UnicodeError, लेकिन क्योंकि आपने व्यापक अपवाद को पकड़ने का उपयोग किया है, आपका कोड, जिसमें अन्य मूलभूत दोष हो सकते हैं, बैंडविड्थ को पूरा करने के लिए चलाने का प्रयास करेंगे। अपने उपकरणों पर समय, प्रसंस्करण, पहनने और आंसू, स्मृति से बाहर चल रहा है, कचरा डेटा एकत्र करना, आदि।

यदि अन्य लोग आपको पूरा करने के लिए कह रहे हैं ताकि वे आपके कोड पर भरोसा कर सकें, तो मैं समझता हूं कि सब कुछ संभालने के लिए मजबूर होना। लेकिन अगर आप अपने विकास के दौरान किसी भी तरह से विफल होने के लिए तैयार हैं, तो आपके पास उन समस्याओं को ठीक करने का अवसर होगा जो केवल रुक-रुक कर पॉप अप कर सकते हैं, लेकिन यह लंबे समय तक महंगा बग होगा।

अधिक सटीक त्रुटि हैंडलिंग के साथ, आप कोड अधिक मजबूत हो सकते हैं।


31
>>> import this

टिम पीटर्स द्वारा ज़ेन ऑफ़ पायथन

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

तो, यहाँ मेरी राय है। जब भी आपको कोई त्रुटि मिलती है, तो आपको इसे संभालने के लिए कुछ करना चाहिए, अर्थात इसे लॉगफ़ाइल या कुछ और में लिखना चाहिए। कम से कम, यह आपको सूचित करता है कि एक त्रुटि हुआ करती थी।


64
-1 प्राधिकरण से तर्क वास्तव में कुछ भी स्पष्ट नहीं करता है। प्राधिकरण गलत हो सकता है।
इजाकाता

23
@ इज़ाकटा ने जो लिखा, और, उसके नीचे एक पंक्ति, वही प्राधिकरण लिखता है: "जब तक स्पष्ट रूप से चुप नहीं किया गया", जो वास्तव में है सिवाय इसके: पास करता है।
ताड़ी रविव

13
@OfriRaviv नहीं, त्रुटि त्रुटि से गुजर रही है ? स्पष्ट रूप से उस त्रुटि को नाम देने की आवश्यकता होगी जो चुपचाप पारित करना चाहिए, अर्थात इसके बारे में स्पष्ट होना । इसके अलावा ऐसा नहीं है: पास करता है।
चेलोनियन

24

आपको except Exception:सिस्टम अपवादों को पकड़ने से बचने के लिए कम से कम उपयोग करना चाहिए SystemExitया जैसे KeyboardInterrupt। यहां डॉक्स का लिंक दिया गया है।

सामान्य तौर पर आपको अवांछित अपवादों को पकड़ने से बचने के लिए स्पष्ट रूप से अपवादों को परिभाषित करना चाहिए जिन्हें आप पकड़ना चाहते हैं। आपको पता होना चाहिए कि आप किन अपवादों को अनदेखा करते हैं


13

सबसे पहले, यह पायथन के ज़ेन के दो सिद्धांतों का उल्लंघन करता है :

  • निहितार्थ की तुलना में स्पष्ट है
  • त्रुटियों को कभी भी चुपचाप नहीं गुजरना चाहिए

इसका क्या मतलब है, यह है कि आप जानबूझकर अपनी गलती को चुपचाप पास करते हैं। इसके अलावा, आप यह नहीं जानते कि कौन सी त्रुटि वास्तव में हुई, क्योंकि except: passकोई भी अपवाद पकड़ लेगा।

दूसरा, अगर हम पायथन के ज़ेन से दूर रहने की कोशिश करते हैं, और सिर्फ पवित्रता की बात करते हैं, तो आपको पता होना चाहिए, कि आपके सिस्टम में बिना किसी ज्ञान और नियंत्रण केexcept:pass पत्तियों का उपयोग करना । अंगूठे का नियम एक अपवाद उठाना है, अगर त्रुटि होती है, और उचित कार्रवाई करें। यदि आप पहले से नहीं जानते हैं, तो ये क्या कार्य होने चाहिए, कम से कम त्रुटि को कहीं लॉग करें (और अपवाद को फिर से बेहतर करें):

try:
    something
except:
    logger.exception('Something happened')

लेकिन, आमतौर पर, यदि आप किसी अपवाद को पकड़ने की कोशिश करते हैं , तो आप शायद कुछ गलत कर रहे हैं!


2
... जब तक स्पष्ट रूप से चुप नहीं हो जाता, ओपी के मामले में यही है।
हाइपरबोरस

मैं आपका समाधान जानना चाहता हूं। वास्तव में, जब वास्तव में कुछ भी करने की आवश्यकता नहीं होती है, मैं केवल त्रुटियों को छोड़कर सूची बनाता हूं और टिप्पणी करता हूं और लॉग लिखता हूं। फिर बस पास।
बूस्टर

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

13
"क्योंकि कुछ लोग ऐसा कहते हैं" वास्तव में "क्यों?" का जवाब नहीं है। सवाल।
सेबेस्टियन नेग्रास्ज़स

12

except:passनिर्माण अनिवार्य रूप से किसी भी और सभी असाधारण स्थिति है कि आने जबकि कोड में शामिल चुप्पी try:ब्लॉक चलाया जा रहा है।

यह बुरा अभ्यास क्या है कि यह आमतौर पर वह नहीं है जो आप वास्तव में चाहते हैं। अधिक बार, कुछ विशिष्ट स्थिति सामने आ रही है कि आप चुप्पी साधना चाहते हैं, और except:passएक कुंद साधन से बहुत अधिक है। यह काम पूरा कर लेगा, लेकिन यह अन्य त्रुटि स्थितियों को भी नाकाम कर देगा, जिसकी आपको संभावना नहीं है, लेकिन बहुत अच्छी तरह से किसी अन्य तरीके से निपटना चाहते हैं।

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


12

# 1 कारण पहले ही बताया जा चुका है - यह उन त्रुटियों को छिपाता है जिनकी आपको उम्मीद नहीं थी।

(# 2) - यह आपके कोड को दूसरों को पढ़ने और समझने में मुश्किल बनाता है। यदि आप एक फ़ाइल को पढ़ने की कोशिश कर रहे हैं, तो आप एक फ़ाइल डेवलपर को पकड़ सकते हैं, तो यह दूसरे डेवलपर के लिए बहुत स्पष्ट है कि 'कैच' ब्लॉक में क्या कार्यक्षमता होनी चाहिए। यदि आप एक अपवाद निर्दिष्ट नहीं करते हैं, तो आपको यह बताने के लिए अतिरिक्त टिप्पणी की आवश्यकता है कि ब्लॉक क्या करना चाहिए।

(# 3) - यह आलसी प्रोग्रामिंग को प्रदर्शित करता है। यदि आप जेनेरिक कोशिश / कैच का उपयोग करते हैं, तो यह इंगित करता है कि आप अपने कार्यक्रम में संभावित रन-टाइम त्रुटियों को नहीं समझते हैं, या यह नहीं जानते हैं कि पायथन में क्या अपवाद संभव हैं। एक विशिष्ट त्रुटि को पकड़ने से पता चलता है कि आप अपने कार्यक्रम और त्रुटियों की सीमा दोनों को समझते हैं जिसे पायथन फेंकता है। यह अन्य डेवलपर्स और कोड-समीक्षकों को आपके काम पर भरोसा करने की अधिक संभावना है।


12

तो, यह कोड किस आउटपुट का उत्पादन करता है?

fruits = [ 'apple', 'pear', 'carrot', 'banana' ]

found = False
try:
     for i in range(len(fruit)):
         if fruits[i] == 'apple':
             found = true
except:
     pass

if found:
    print "Found an apple"
else:
    print "No apples in list"

अब कल्पना करें try- exceptब्लॉक एक जटिल वस्तु पदानुक्रम के लिए कॉल की सैकड़ों लाइनें हैं, और खुद को बड़े कार्यक्रम के कॉल ट्री के बीच में कहा जाता है। जब कार्यक्रम गलत हो जाता है, तो आप कहां देखना शुरू करते हैं?


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

11

सामान्य तौर पर, आप तीन श्रेणियों में से किसी भी त्रुटि / अपवाद को वर्गीकृत कर सकते हैं :

  • घातक : आपकी गलती नहीं, आप उन्हें रोक नहीं सकते, आप उनसे उबर नहीं सकते। आपको निश्चित रूप से उन्हें अनदेखा नहीं करना चाहिए और जारी रखना चाहिए, और अपने कार्यक्रम को अज्ञात स्थिति में छोड़ देना चाहिए। बस त्रुटि को अपने कार्यक्रम को समाप्त करने दें, ऐसा कुछ भी नहीं है जो आप कर सकते हैं।

  • हड्डीवाला : आपकी खुद की गलती, सबसे अधिक संभावना एक निगरानी, ​​बग या प्रोग्रामिंग त्रुटि के कारण। आपको बग को ठीक करना चाहिए। फिर से, आपको सबसे निश्चित रूप से अनदेखा नहीं करना चाहिए और जारी रखना चाहिए।

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

सभी मामलों except: passमें केवल आपके कार्यक्रम को अज्ञात स्थिति में छोड़ देगा, जहां यह अधिक नुकसान पहुंचा सकता है।


6

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

समस्याओं से निपटने की जरूरत है। जैसे कि यह जीवन में कैसा है, प्रोग्रामिंग में, यदि आप सिर्फ समस्याओं को अकेले छोड़ देते हैं और उन्हें अनदेखा करने की कोशिश करते हैं, तो वे बहुत बार खुद से दूर नहीं जाते हैं; इसके बजाय वे बड़े और गुणा हो जाते हैं। एक समस्या को आप पर बढ़ने से रोकने के लिए और सड़क को फिर से नीचे की ओर धकेलने के लिए, आप या तो 1) इसे समाप्त करें और बाद में गंदगी को साफ करें, या 2) इसे शामिल करें और बाद में गंदगी को साफ करें।

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

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

मेरी कंपनी में नियम लगभग हमेशा क्या करना है कुछ कैच ब्लॉक में है, और आप कुछ नहीं करते हैं, तो आप हमेशा एक बहुत अच्छे कारण के साथ एक टिप्पणी क्यों नहीं डालना चाहिए। जब भी कुछ भी करना हो, तो आपको कभी भी खाली कैच ब्लॉक को पास या छोड़ना नहीं चाहिए।


6

मेरी राय में त्रुटियों के कारण प्रकट होता है, कि मेरी आवाज बेवकूफ है, लेकिन यह जिस तरह से है। अच्छी प्रोग्रामिंग केवल त्रुटियों को उठाती है जब आपको उन्हें संभालना होता है। इसके अलावा, जैसा कि मैंने कुछ समय पहले पढ़ा था, "पास-स्टेटमेंट एक स्टेटमेंट है, जो शो कोड बाद में डाला जाएगा", इसलिए यदि आप एक खाली-अपवाद चाहते हैं तो स्टेटमेंट ऐसा करने के लिए स्वतंत्र महसूस करता है, लेकिन एक अच्छे कार्यक्रम के लिए एक हिस्सा गायब है। क्योंकि आप उन चीजों को नहीं संभालते हैं जो आपके पास होनी चाहिए। अपवादों को देखने से आपको इनपुट डेटा को सही करने या अपनी डेटा संरचना को बदलने का मौका मिलता है ताकि ये अपवाद फिर से न हों (लेकिन ज्यादातर मामलों में (नेटवर्क-अपवाद, सामान्य इनपुट-अपवाद) अपवाद यह इंगित करते हैं कि प्रोग्राम के अगले भाग अच्छी तरह से निष्पादित नहीं होंगे। उदाहरण के लिए एक NetworkException टूटे हुए नेटवर्क-कनेक्शन और प्रोग्राम को अगले प्रोग्राम चरणों में डेटा भेजने / प्राप्त करने का संकेत दे सकता है।

लेकिन केवल एक निष्पादन-ब्लॉक के लिए एक पास ब्लॉक का उपयोग करना मान्य है, क्योंकि आप अभी भी अपवादों के प्रकारों को परिभाषित करते हैं, इसलिए यदि आप सभी अपवाद-ब्लॉकों को एक में रखते हैं, तो यह खाली नहीं है:

try:
    #code here
except Error1:
    #exception handle1

except Error2:
    #exception handle2
#and so on

इस तरह से फिर से लिखा जा सकता है:

try:
    #code here
except BaseException as e:
    if isinstance(e, Error1):
        #exception handle1

    elif isinstance(e, Error2):
        #exception handle2

    ...

    else:
        raise

तो पास-स्टेटमेंट वाले कई अपवाद भी कोड में परिणाम कर सकते हैं, जिनकी संरचना विशेष प्रकार के अपवादों को संभालती है।


4

अब तक लाई गई सभी टिप्पणियाँ मान्य हैं। जहां संभव हो आपको यह निर्दिष्ट करने की आवश्यकता है कि आप किस अपवाद को अनदेखा करना चाहते हैं। जहां संभव हो आपको विश्लेषण करने की आवश्यकता है कि अपवाद का कारण क्या है, और केवल इस बात को अनदेखा करें कि आपको अनदेखा करने का क्या मतलब है, और बाकी नहीं। यदि अपवाद "शानदार ढंग से क्रैश" करने के लिए आवेदन का कारण बनता है, तो यह हो, क्योंकि अप्रत्याशित रूप से यह जानना बहुत महत्वपूर्ण है कि ऐसा कब हुआ था, यह छिपाने के बजाय कि समस्या कभी हुई।

कहा कि सभी के साथ, किसी भी प्रोग्रामिंग अभ्यास को एक सर्वोपरि के रूप में न लें। यह बेवकूफी है। हमेशा उपेक्षा करने वाले सभी अपवादों को करने का समय और स्थान होता है।

अज्ञात सर्वोपरि का एक और उदाहरण gotoऑपरेटर का उपयोग है । जब मैं स्कूल में था, तो हमारे प्रोफेसर ने हमें gotoऑपरेटर को केवल यह उल्लेख करने के लिए सिखाया कि आप इसका उपयोग नहीं करेंगे, कभी। विश्वास न करें कि लोग आपको बता रहे हैं कि xyz का उपयोग कभी नहीं किया जाना चाहिए और उपयोगी होने पर परिदृश्य नहीं हो सकता है। हमेशा है।


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

1
@Score_Under अभी तक ऐसे मामले हैं जहां यह उपयोग करना उचित है। उदाहरण के लिए जब आप किसी फ़ंक्शन को कॉल कर रहे हैं, तो वह अज्ञात मूल / लेखक का पूरक है, कोर कार्यक्षमता को प्रभावित नहीं करता है, लेकिन अगर क्रैश परेशानी पैदा कर सकता है। मुझे लगता है कि आप तर्क देंगे कि इस तरह की कॉलों का सही तरीके से अनुसंधान और विश्लेषण किया जाना चाहिए, लेकिन वास्तविक जीवन में यह हमेशा संभव नहीं है।
17

फिर भी, अगर मैं आपकी प्रक्रिया को समाप्त करना चाहता हूं, तो किल -9 एकमात्र विश्वसनीय विकल्प नहीं होना चाहिए।
स्कोर_उंडर

2

प्रोग्रामिंग में त्रुटियों को संभालना बहुत महत्वपूर्ण है। आपको उपयोगकर्ता को यह दिखाने की आवश्यकता है कि क्या गलत हुआ। बहुत कम मामलों में आप त्रुटियों को अनदेखा कर सकते हैं। यह है यह बहुत बुरा प्रोग्रामिंग अभ्यास है।


2

चूंकि इसका अभी तक उल्लेख नहीं किया गया है, इसलिए इसका उपयोग करना बेहतर शैली है contextlib.suppress:

with suppress(FileNotFoundError):
    os.remove('somefile.tmp')

ध्यान दें कि प्रदान किए गए उदाहरण में, कार्यक्रम की स्थिति समान है, चाहे अपवाद हो या न हो। यह कहना है, somefile.tmpहमेशा अस्तित्वहीन हो जाता है।

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