Chapter 01 Exception Handling in Python

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

$\quad$ - बजार्ने स्ट्राउस्ट्रुप

1.1 परिचय

कभी-कभी कोई Python प्रोग्राम चलाते समय या तो प्रोग्राम बिल्कुल नहीं चलता, या प्रोग्राम चल तो जाता है पर अप्रत्याशित आउटपुट देता है या असामान्य व्यवहार करता है। ये तब होता है जब कोड में वाक्य-रचना त्रुटियाँ, रनटाइम त्रुटियाँ या तार्किक त्रुटियाँ होती हैं। Python में अपवाद (exceptions) वे त्रुटियाँ हैं जो स्वचालित रूप से ट्रिगर होती हैं। हालाँकि, अपवादों को जानबूझकर भी ट्रिगर किया जा सकता है और प्रोग्राम कोड के माध्यम से संभाला जा सकता है। इस अध्याय में हम Python प्रोग्रामों में अपवाद-प्रबंधन सीखेंगे।

1.2 वाक्य-रचना त्रुटियाँ

वाक्य-रचना त्रुटियाँ तब पकड़ी जाती हैं जब हम प्रोग्राम लिखते समय किसी विशेष प्रोग्रामिंग भाषा के नियमों का पालन नहीं करते। इन्हें पार्सिंग त्रुटियाँ भी कहा जाता है। वाक्य-रचना त्रुटि आने पर, जब तक हम त्रुटियों को सुधारकर प्रोग्राम को सहेजते और पुनः नहीं चलाते, तब तक इंटरप्रेटर प्रोग्राम को नहीं चलाता। जब शेल मोड में काम करते समय कोई वाक्य-रचना त्रुटि आती है, तो Python त्रुटि का नाम और त्रुटि के बारे में संक्षिप्त विवरण दिखाता है, जैसा कि चित्र 1.1 में दिखाया गया है।

चित्र 1.1: पायथन शेल मोड में दिखाया गया एक वाक्य-रचना त्रुटि

इस प्रकार, पायथन दुभाषिया एक वाक्य-रचना त्रुटि की रिपोर्ट करता है जिसमें त्रुटि के बारे में संक्षिप्त व्याख्या और उसे सुधारने का सुझाव दिया जाता है।

इसी प्रकार, जब स्क्रिप्ट मोड में कोई प्रोग्राम चलाते समय वाक्य-रचना त्रुटि आती है, जैसा कि चित्र 1.2 में दिखाया गया है, तो एक संवाद बॉक्स प्रदर्शित होता है जो त्रुटि का नाम (चित्र 1.3) और त्रुटि के बारे में संक्षिप्त विवरण देता है।

1.3 एक्सेप्शन्स (अपवाद)

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

एक अपवाद एक पायथन वस्तु है जो एक त्रुटि का प्रतिनिधित्व करती है। जब किसी प्रोग्राम के निष्पादन के दौरान कोई त्रुटि होती है, तो कहा जाता है कि एक अपवाद उठाया गया है। ऐसे अपवाद को प्रोग्रामर द्वारा संभालना पड़ता है ताकि प्रोग्राम असामान्य रूप से समाप्त न हो। इसलिए, किसी प्रोग्राम को डिज़ाइन करते समय एक प्रोग्रामर उन गलत परिस्थितियों का पूर्वानुमान लगा सकता है जो निष्पादन के दौरान उत्पन्न हो सकती हैं और उस अपवाद को संभालने के लिए उपयुक्त कोड शामिल करके उनका समाधान कर सकता है।

यह ध्यान देने योग्य है कि आकृति 1.1 और 1.3 में दिखाया गया SyntaxError भी एक अपवाद है। लेकिन, सभी अन्य अपवाद तब उत्पन्न होते हैं जब कोई प्रोग्राम वाक्य-रचनात्मक रूप से सही हो।

1.4 निर्मित-अपवाद (BUILT-IN EXCEPTIONS)

आमतौर पर होने वाले अपवाद सामान्यतः कंपाइलर/इंटरप्रेटर में परिभाषित होते हैं। इन्हें निर्मित-अपवाद कहा जाता है।

Python का मानक पुस्तकालय निर्मित-अपवादों का एक विस्तृत संग्रह है, जो सामान्यतः होने वाली त्रुटियों (अपवादों) से निपटने के लिए ऐसी त्रुटियों के लिए मानकीकृत समाधान प्रदान करता है। किसी निर्मित-अपवाद की घटना पर, उपयुक्त अपवाद-हैंडलर कोड निष्पादित होता है जो उठाए गए अपवाद के नाम के साथ कारण प्रदर्शित करता है। प्रोग्रामर को फिर उसे संभालने के लिए उपयुक्त कार्रवाई करनी होती है। कुछ सामान्यतः होने वाले निर्मित-अपवाद जो Python में उठाए जा सकते हैं, सारणी 1.1 में समझाए गए हैं।

$\hspace{5cm}$ सारणी 1.1 Python में निर्मित अपवाद

क्र. सं. अंतर्निहित अपवाद का नाम व्याख्या
1. SyntaxError यह Python कोड की वाक्य-रचना में त्रुटि होने पर उत्पन्न होता है।
2. ValueError यह तब उत्पन्न होता है जब कोई अंतर्निहित विधि या संचालन सही डेटा प्रकार का तर्क प्राप्त करता है,
लेकिन मान असंगत या अनुपयुक्त होता है।
3. IOError यह तब उत्पन्न होता है जब प्रोग्राम कथन में निर्दिष्ट फ़ाइल को
खोला नहीं जा सकता।
4 Keyboardinterrupt यह तब उत्पन्न होता है जब उपयोगकर्ता प्रोग्राम चलाते समय गलती से Delete या Esc कुंजी दबा देता है,
जिससे प्रोग्राम की सामान्य प्रवाह बाधित हो जाती है।
5 ImportError यह तब उत्पन्न होता है जब अनुरोधित मॉड्यूल परिभाषा नहीं मिलती।
6 EOFError यह तब उत्पन्न होता है जब input() द्वारा कोई डेटा पढ़े बिना ही फ़ाइल के अंत की स्थिति आ जाती है।
7 ZeroDivisionError यह तब उत्पन्न होता है जब भाग संचालन में हर शून्य होता है।
8 IndexError यह तब उत्पन्न होता है जब क्रम में सूचकांक या उपसूचक सीमा से बाहर होता है।
9 NameError यह तब उत्पन्न होता है जब कोई स्थानीय या वैश्विक चर नाम परिभाषित नहीं होता।
10 IndentationError यह प्रोग्राम कोड में गलत इंडेंटेशन के कारण उत्पन्न होता है।
11 TypeError यह तब उत्पन्न होता है जब किसी संचालन को गलत डेटा प्रकार का मान दिया जाता है।
12 OverFlowError यह तब उत्पन्न होता है जब गणना का परिणाम संख्यात्मक डेटा प्रकार की अधिकतम सीमा से अधिक हो जाता है।

चित्र 1.4 में अंतर्निहित अपवादों, अर्थात् ZeroDivisionError, NameError और TypeError को दिखाया गया है जो विभिन्न परिस्थितियों में Python दुभाषिये द्वारा उत्पन्न किए जाते हैं।

चित्र 1.4: अंतर्निहित अपवादों का उदाहरण

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

1.5 अपवादों को उत्पन्न करना

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

1.5.1 raise कथन

raise कथन का उपयोग करके एक अपवाद फेंका जा सकता है। raise कथन का वाक्य-विन्यास इस प्रकार है:

raise अपवाद-नाम[(वैकल्पिक तर्क)]

आमतौर पर तर्क एक स्ट्रिंग होता है जो एक्सेप्शन उठाए जाने पर प्रदर्शित होता है। उदाहरण के लिए, जब एक्सेप्शन को चित्र 1.5 में दिखाए अनुसार उठाया जाता है, तो संदेश “OOPS : An Exception has occurred” त्रुटि के संक्षिप्त विवरण के साथ प्रदर्शित होता है।

चित्र 1.5: एक्सेप्शन फेंकने के लिए raise स्टेटमेंट का उपयोग

पता लगाई गई त्रुटि एक बिल्ट-इन एक्सेप्शन हो सकती है या उपयोगकर्ता-परिभाषित भी हो सकती है। चित्र 1.6 में दिए गए उदाहरण पर विचार करें जो IndexError नामक एक बिल्ट-इन एक्सेप्शन को उठाने के लिए raise स्टेटमेंट का उपयोग करता है।

नोट: इस मामले में, उपयोगकर्ता ने केवल एक्सेप्शन उठाया है लेकिन कोई त्रुटि संदेश स्पष्ट रूप से प्रदर्शित नहीं किया है।

चित्र 1.6 में, चूँकि चर length का मान सूची numbers की लंबाई से अधिक है, एक IndexError एक्सेप्शन उठाया जाएगा। raise स्टेटमेंट के बाद आने वाला स्टेटमेंट निष्पादित नहीं होगा। इसलिए इस मामले में संदेश “NO EXECUTION” प्रदर्शित नहीं होगा।

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

चित्र 1.6: अंतर्निहित अपवाद के साथ raise कथन का उपयोग

नोट: हम अध्याय 3 में स्टैक के बारे में सीखेंगे।

1.5.2 assert कथन

Python में एक assert कथन प्रोग्राम कोड में किसी अभिव्यक्ति का परीक्षण करने के लिए प्रयोग किया जाता है। यदि परीक्षण के बाद परिणाम असत्य आता है, तो अपवाद उत्पन्न होता है। यह कथन सामान्यतः फ़ंक्शन की शुरुआत में या फ़ंक्शन कॉल के बाद वैध इनपुट की जाँच के लिए प्रयोग किया जाता है। assert कथन के लिए वाक्य-रचना है:

assert अभिव्यक्ति[, तर्क]

जब Python को कोई assert कथन मिलता है, तो वह assert कीवर्ड के तुरंत बाद दी गई अभिव्यक्ति का मूल्यांकन करता है। यदि यह अभिव्यक्ति असत्य है, तो एक AssertionError अपवाद उत्पन्न होता है जिसे किसी अन्य अपवाद की तरह संभाला जा सकता है। प्रोग्राम 1-1 में दिए गए कोड पर विचार करें।

प्रोग्राम 1-1 assert कथन का उपयोग

print("assert कथन का उपयोग")
def negativecheck(number):
    assert(number>=0), "ओह... नकारात्मक संख्या"
    print(number*number)
print (negativecheck(100))
print (negativecheck(-350))

आकृति 1.7: प्रोग्राम 1-1 का आउटपुट।

कोड में, assert कथन चर number के मान की जाँच करता है। यदि number को नकारात्मक मान मिलता है, तो AssertionError फेंका जाएगा, और आगे के कथन निष्पादित नहीं होंगे। इसलिए, एक नकारात्मक मान (-350) को तर्क के रूप में पास करने पर यह AssertionError का परिणाम देता है और संदेश “ओह…. नकारात्मक संख्या” प्रदर्शित करता है। कोड का आउटपुट आकृति 1.7 में दिखाया गया है।

1.6 अपवादों को संभालना

प्रत्येक अपवाद को प्रोग्रामर द्वारा संभालना होता है ताकि प्रोग्राम अचानक क्रैश न हो। यह प्रोग्राम में अतिरिक्त कोड लिखकर किया जाता है ताकि किसी अपवाद का सामना करने पर उपयोगकर्ता को उचित संदेश या निर्देश दिए जा सकें। इस प्रक्रिया को अपवाद संभालना कहा जाता है।

1.6.1 अपवाद संभालने की आवश्यकता

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

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

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

1.6.2 एक्सेप्शन हैंडलिंग की प्रक्रिया

जब कोई त्रुटि होती है, तो Python interpreter एक ऑब्जेक्ट बनाता है जिसे exception object कहा जाता है। यह ऑब्जेक्ट त्रुटि के बारे में जानकारी रखता है जैसे इसका प्रकार, फ़ाइल का नाम और प्रोग्राम में वह स्थान जहाँ त्रुटि हुई है। यह ऑब्जेक्ट runtime system को सौंपा जाता है ताकि वह इस विशेष exception को संभालने के लिए उपयुक्त कोड खोज सके। exception object बनाने और उसे runtime system को सौंपने की इस प्रक्रिया को throwing an exception कहा जाता है। यह ध्यान रखना महत्वपूर्ण है कि जब किसी विशेष प्रोग्राम statement को निष्पादित करते समय कोई exception होती है, तो नियंत्रण exception handler पर कूद जाता है, शेष प्रोग्राम statements के निष्पादन को छोड़कर।

Runtime system पूरे प्रोग्राम में कोड के एक ब्लॉक की खोज करता है, जिसे exception handler कहा जाता है, जो उठाए गए exception को संभाल सकता है। यह पहले उस method की खोज करता है जिसमें त्रुटि हुई है और exception उठाया गया है। यदि नहीं मिलता, तो यह उस method की खोज करता है जिससे यह method (जिसमें exception उठाया गया था) बुलाया गया था। यह उलटे क्रम में पदानुक्रमित खोज तब तक जारी रहती है जब तक exception handler नहीं मिल जाता। यह पूरी methods की सूची call stack के रूप में जानी जाती है। जब call stack में कोई उपयुक्त handler मिल जाता है, तो उसे runtime process द्वारा निष्पादित किया जाता है। उपयुक्त handler को निष्पादित करने की इस प्रक्रिया को catching the exception कहा जाता है। यदि runtime system call stack में सभी methods की खोज करने के बाद भी कोई उपयुक्त exception नहीं ढूंढ पाता, तो प्रोग्राम execution रुक जाता है।

फ़्लोचार्ट जो चित्र 1.8 में दिया गया है, अपवाद-हैंडलिंग प्रक्रिया को दर्शाता है।

चित्र 1.8: अपवाद को संभालने के चरण

1.6.3 अपवादों को पकड़ना

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

प्रोग्राम चलाते समय यदि कोई अपवाद आता है, तो try ब्लॉक के अंदर कोड की आगे की निष्पादना रोक दी जाती है और नियंत्रण except ब्लॉक में स्थानांतरित कर दिया जाता है। try … except खंड की वाक्य-रचना इस प्रकार है:

try:
$\quad$ [प्रोग्रम कथन जहाँ अपवाद आ सकते हैं]
except [exception-name]:
$\quad$ [अपवाद-नाम त्रुटि आने पर अपवाद-हैंडलिंग के लिए कोड]

नीचे दिया गया प्रोग्रम 1-2 देखें:

प्रोग्रम 1-2 try..except ब्लॉक का उपयोग

print ("Practicing for try block")
try:
    numerator=50
    denom=int(input("Enter the denominator"))
    quotient=(numerator/denom)
    print(quotient)
    print ("Division performed successfully")
except ZeroDivisionError:
    print ("Denominator as ZERO.... not allowed")
print("OUTSIDE try..except block")

प्रोग्राम 1-2 में, ZeroDivisionError अपवाद को संभाला गया है। यदि उपयोगकर्ता किसी भी गैर-शून्य मान को हर के रूप में दर्ज करता है, तो भागफल “Division performed successfully” संदेश के साथ प्रदर्शित किया जाएगा, जैसा कि चित्र 1.10 में दिखाया गया है। इस स्थिति में except खंड छोड़ दिया जाएगा। इसलिए, try..except ब्लॉक के बाद अगला कथन निष्पादित किया जाता है और संदेश “OUTSIDE try.. except block” प्रदर्शित होता है।

हालांकि, यदि उपयोगकर्ता denom का मान शून्य (0) दर्ज करता है, तो try ब्लॉक का निष्पादन रुक जाएगा। नियंत्रण except ब्लॉक में स्थानांतरित हो जाएगा और संदेश “Denominator as Zero…. not allowed” प्रदर्शित किया जाएगा, जैसा कि चित्र 1.11 में दिखाया गया है। तत्पश्चात, try..except ब्लॉक के बाद कथन निष्पादित किया जाता है और इस स्थिति में भी संदेश “OUTSIDE try..except block” प्रदर्शित होता है।

चित्र 1.9: त्रुटि के बिना आउटपुट

आकृति 1.10: अपवाद उत्पन्न होने पर आउटपुट

कभी-कभी, एक ही कोड में एक से अधिक प्रकार की त्रुटियाँ होने की संभावना होती है। ऐसी स्थितियों को संभालने के लिए, हम एक ही try ब्लॉक के लिए कई except ब्लॉक रख सकते हैं, जैसा कि प्रोग्राम 1-3 में दिखाया गया है।

प्रोग्राम 1-3 एकाधिक except खंडों का उपयोग

print (“Handling multiple exceptions”)
try:
$\quad$ numerator=50
$\quad$ denom=int(input(“Enter the denominator: “))
$\quad$ print (numerator/denom)
$\quad$ print (“Division performed successfully”)
except ZeroDivisionError:
$\quad$ print (“Denominator as ZERO is not allowed”)
except ValueError:
$\quad$ print (“Only INTEGERS should be entered”)

इस कोड में, दो प्रकार के अपवाद (ZeroDivisionError और ValueError) को एक ही try ब्लॉक के लिए दो except ब्लॉक का उपयोग करके संभाला गया है। जब कोई अपवाद उत्पन्न होता है, तब मिलान करने वाला except ब्लॉक खोजा जाता है जब तक कि वह संभाल न लिया जाए। यदि कोई मिलान नहीं मिलता, तो प्रोग्राम समाप्त हो जाता है।

हालाँकि, यदि कोई ऐसा अपवाद उत्पन्न होता है जिसके लिए प्रोग्रामर द्वारा कोई हैंडलर नहीं बनाया गया है, तो ऐसे अपवाद को बिना कोई अपवाद निर्दिष्ट किए एक except खंड जोड़कर संभाला जा सकता है। इस except खंड को try..except ब्लॉक के अंतिम खंड के रूप में जोड़ा जाना चाहिए। नीचे दिया गया प्रोग्राम 1-4 और चित्र 1.11 में दिया गया आउटपुट इसे समझाते हैं।

प्रोग्राम 1-4 किसी अपवाद को निर्दिष्ट किए बिना except का उपयोग

print (“Handling exceptions without naming them”)
try:
$\quad$ numerator=50
$\quad$ denom=int(input(“Enter the denominator”))
$\quad$ quotient=(numerator/denom)
$\quad$ print (“Division performed successfully”)
except ValueError:
$\quad$ print (“Only INTEGERS should be entered”)
except:
$\quad$ print(” OOPS…..SOME EXCEPTION RAISED”)

यदि उपरोक्त कोड को निष्पादित किया जाता है, और हर 0 (शून्य) दर्ज किया जाता है, तो ZeroDivisionError अपवाद के लिए हैंडलर खोजा जाएगा। चूँकि यह मौजूद नहीं है, अंतिम except खंड (बिना कोई निर्दिष्ट अपवाद) निष्पादित होगा, इसलिए संदेश " OOPS…..SOME EXCEPTION RAISED" प्रदर्शित होगा।

चित्र 1.11: प्रोग्राम 1-4 का आउटपुट

1.6.4 try . . . except…else खंड

हम try… except खंड के साथ एक वैकल्पिक else खंड रख सकते हैं। एक except ब्लॉक तभी निष्पादित होगा जब try ब्लॉक में कोई अपवाद उठाया गया हो। लेकिन अगर कोई त्रुटि नहीं है तो कोई भी except ब्लॉक निष्पादित नहीं होगा। इस स्थिति में, else खंड के अंदर के कथन निष्पादित होंगे। प्रोग्राम 1-5 अपने आउटपुट के साथ try… except ब्लॉक के साथ else ब्लॉक के उपयोग को समझाता है।

प्रोग्राम 1-5 else खंड का उपयोग

print (“Handling exception using try…except…else”)
try:
$\quad$ numerator=50
$\quad$ denom=int(input(“Enter the denominator: “))
$\quad$ quotient=(numerator/denom)
$\quad$ print (“Division performed successfully”)

except ZeroDivisionError:
$\quad$ print (“Denominator as ZERO is not allowed”)

except ValueError:
$\quad$ print (“Only INTEGERS should be entered”)

else:
$\quad$ print (“The result of division operation is “, quotient)

आउटपुट:

चित्र 1.12: प्रोग्राम 1-5 का आउटपुट।

1.7 FINALLY खंड

Python में try statement में एक वैकल्पिक finally clause भी हो सकती है। finally ब्लॉक के अंदर के कथन हमेशा निष्पादित होते हैं, चाहे try ब्लॉक में कोई exception आया हो या नहीं। फ़ाइलों के साथ काम करते समय यह सुनिश्चित करने के लिए कि फ़ाइल ऑब्जेक्ट बंद हो जाए, finally clause का उपयोग करना एक सामान्य अभ्यास है। यदि उपयोग किया जाए, तो finally को हमेशा try clause के अंत में, सभी except ब्लॉकों और else ब्लॉक के बाद रखा जाना चाहिए।

Program 1-6 finally clause का उपयोग

print (“Handling exception using try…except…else…finally”)
try:
$\quad$ numerator=50
$\quad$ denom=int(input(“Enter the denominator: “))
$\quad$ quotient=(numerator/denom)
$\quad$ print (“Division performed successfully”)
except ZeroDivisionError:
$\quad$ print (“Denominator as ZERO is not allowed”)
except ValueError:
$\quad$ print (“Only INTEGERS should be entered”)
else:
$\quad$ print (“The result of division operation is “, quotient)
finally:
$\quad$ print (“OVER AND OUT”)

उपरोक्त प्रोग्राम में, संदेश “OVER AND OUT” तब भी प्रदर्शित होगा जब कोई exception उठाया गया हो या नहीं।

1.6.1 Recovering and continuing with finally clause

यदि try ब्लॉक में कोई त्रुटि पकड़ी गई है और exception फेंक दिया गया है, तो उपयुक्त except ब्लॉक उस त्रुटि को संभालने के लिए चलाया जाएगा। लेकिन यदि exception किसी भी except clause द्वारा संभाला नहीं गया, तो वह finally ब्लॉक के निष्पादन के बाद फिर से उठाया जाता है। उदाहरण के लिए, Program 1.4 में केवल ZeroDivisionError के लिए except ब्लॉक है। यदि कोई अन्य प्रकार की त्रुटि होती है जिसके लिए कोई handler code (except clause) परिभाषित नहीं है, तब भी finally clause पहले निष्पादित होगी। इन अवधारणाओं को समझने के लिए Program 1-7 में दिया गया कोड देखें।

Program 1-7 finally clause के माध्यम से पुनः प्राप्ति

print (” Practicing for try block”)
try:
$\quad$ numerator=50
$\quad$ denom=int(input(“Enter the denominator”))
$\quad$ quotient=(numerator/denom)
$\quad$ print (“Division performed successfully”)
except ZeroDivisionError:
$\quad$ print (“Denominator as ZERO is not allowed”)
else:
$\quad$ print (“The result of division operation is “, quotient)
finally:
$\quad$ print (“OVER AND OUT”)

उपरोक्त कोड को चलाते समय, यदि हम इनपुट के रूप में गैर-संख्यात्मक डेटा दर्ज करते हैं, तो finally ब्लॉक निष्पादित होगा। इसलिए संदेश “OVER AND OUT” प्रदर्शित होगा। तत्पश्चात वह exception जिसके लिए handler मौजूद नहीं है, फिर से उठाया जाएगा। Program 1-7 का आउटपुट Figure 1.13 में दिखाया गया है।

आकृति 1.13: प्रोग्राम 1-7 का आउटपुट

फाइनली ब्लॉक के निष्पादन के बाद, Python नियंत्रण को पहले दर्ज किए गए try में या अगले उच्च स्तर के डिफ़ॉल्ट एक्सेप्शन हैंडलर को स्थानांतरित करता है। ऐसी स्थिति में, फाइनली ब्लॉक के बाद आने वाले कथन निष्पादित होते हैं। यानी, एक्सेप्ट के विपरीत, फाइनली क्लॉज का निष्पादन एक्सेप्शन को समाप्त नहीं करता है। बल्कि, फाइनली के निष्पादन के बाद एक्सेप्शन उठता रहता है।

संक्षेप में, हम उस कोड के टुकड़े को try ब्लॉक के अंदर रखते हैं जहाँ त्रुटियों या एक्सेप्शन आने की संभावना होती है। प्रत्येक except क्लॉज के अंदर हम try ब्लॉक में उठाए गए मिलान एक्सेप्शन को संभालने के लिए हैंडलर कोड परिभाषित करते हैं। वैकल्पिक else क्लॉज में वह कोड होता है जो कोई एक्सेप्शन न आने पर निष्पादित होता है। वैकल्पिक finally ब्लॉक में वह कोड होता है जो चाहे एक्सेप्शन आए या न आए, निष्पादित होता है।

सारांश

  • सिंटेक्स त्रुटियाँ या पार्सिंग त्रुटियाँ तब पकड़ी जाती हैं जब हमने किसी विशेष प्रोग्रामिंग भाषा के नियमों का पालन नहीं किया होता है जबकि प्रोग्राम लिख रहे होते हैं।
  • जब सिंटेक्स त्रुटि आती है, तो Python त्रुटि का नाम और त्रुटि के बारे में एक छोटा विवरण दिखाता है।
  • प्रोग्राम की निष्पादन तभी शुरू होता है जब सिंटेक्स त्रुटि को ठीक कर दिया जाता है।
  • एक अपवाद (exception) एक Python वस्तु है जो त्रुटि का प्रतिनिधित्व करती है।
  • सिंटेक्स त्रुटियों को भी अपवादों के रूप में संभाला जाता है।
  • अपवाद को प्रोग्रामर द्वारा संभालना पड़ता है ताकि प्रोग्राम अचानक समाप्त न हो।
  • जब किसी प्रोग्राम के निष्पादन के दौरान कोई अपवाद आता है और उसके लिए कोई अंतर्निहित अपवाद परिभाषित है, तो उस अपवाद में लिखा गया त्रुटि संदेश प्रदर्शित होता है। फिर प्रोग्रामर को उपयुक्त कार्रवाई करनी होती है और उसे संभालना होता है।
  • कुछ सामान्यतः आने वाले अंतर्निहित अपवाद हैं SyntaxError, ValueError, IOError, KeyboardInterrupt, ImportError, EOFError, ZeroDivisionError, IndexError, NameError, IndentationError, TypeError, और overflowerror।
  • जब किसी प्रोग्राम में कोई त्रुटि आती है, तो Python इंटरप्रेटर एक अपवाद उठाता है या फेंकता है।
  • अपवाद हैंडलर वे कोड होते हैं जो किसी विशिष्ट अपवाद के उठने पर निष्पादित होने के लिए डिज़ाइन किए गए होते हैं।
  • किसी अपवाद को उठाना इस बात को शामिल करता है कि प्रोग्राम निष्पादन के सामान्य प्रवाह को बाधित किया जाए और अपवाद हैंडलर पर कूदा जाए।
  • Raise और assert कथन अपवाद उठाने के लिए प्रयोग किए जाते हैं।
  • अपवाद संभालने की प्रक्रिया में उपयोगकर्ता को उचित संदेश या निर्देश देने के लिए अतिरिक्त कोड लिखना शामिल होता है। यह प्रोग्राम को अचानक क्रैश होने से रोकता है। यह अतिरिक्त कोड अपवाद हैंडलर कहलाता है।
  • एक अपवाद को पकड़ा गया कहा जाता है जब कोई कोड जो किसी विशेष अपवाद को संभालने के लिए डिज़ाइन किया गया है, निष्पादित होता है।
  • एक अपवाद try ब्लॉक में पकड़ा जाता है और except ब्लॉक में संभाला जाता है।
  • finally ब्लॉक के अंदर के कथन हमेशा निष्पादित होते हैं चाहे try ब्लॉक में कोई अपवाद आया हो या नहीं।

अभ्यास

1. “हर सिंटैक्स एरर एक एक्सेप्शन होता है लेकिन हर एक्सेप्शन सिंटैक्स एरर नहीं हो सकता।” कथन को उचित ठहराएं।

2. निम्नलिखित बिल्ट-इन एक्सेप्शन्स कब उठाए जाते हैं? अपने उत्तर का समर्थन करने के लिए उदाहरण दें।

a) ImportError
b) IOError
c) NameError
d) ZeroDivisionError

3. raise स्टेटमेंट का क्या उपयोग है? दो संख्याएँ स्वीकार करने और भागफल प्रदर्शित करने के लिए कोड लिखें। यदि उपयोगकर्ता दूसरी संख्या (हर) 0 (शून्य) के रूप में दर्ज करता है तो उपयुक्त एक्सेप्शन उठाया जाना चाहिए।

4. प्रोग्राम में भाग की अभिव्यक्ति का परीक्षण करने के लिए प्रश्न संख्या 3 में assert स्टेटमेंट का प्रयोग करें।

5. निम्नलिखित को परिभाषित करें:

a) Exception Handling
b) Throwing an exception
c) Catching an exception

6. try और except ब्लॉक का उपयोग करके एक्सेप्शन्स को पकड़ने की व्याख्या करें।

7. नीचे दिए गए कोड पर विचार करें और रिक्त स्थानों को भरें।

print (” Learning Exceptions…”)
try:
$\quad$ num1= int(input (“Enter the first number”))
$\quad$ num2=int(input(“Enter the second number”))
$\quad$ quotient=(num1/num2)
$\quad$ print (“Both the numbers entered were correct”)
except _____________: $\qquad$ # to enter only integers
$\quad$ print (” Please enter only numbers”)
except ____________: $\qquad$ # Denominator should not be zero
$\quad$ print(” Number 2 should not be zero”)
else:
$\quad$ print(” Great .. you are a good programmer”)
___________: $\qquad$ # to be executed at the end
$\quad$ print(" JOB OVER… GO GET SOME REST")

8. आपने कक्षा ग्यारह में math मॉड्यूल का उपयोग करना सीखा है। एक कोड लिखिए जिसमें आप किसी विधि (जैसे sqrt() या pow()) के लिए गलत संख्या में तर्कों का उपयोग करते हैं। ValueError अपवाद को पकड़ने के लिए अपवाद हैंडलिंग प्रक्रिया का उपयोग करें।

9. finally खंड का क्या उपयोग है? प्रश्न संख्या 7 में दी गई समस्या में finally खंड का उपयोग करें।