हमें पायथन में "अंत" खंड की आवश्यकता क्यों है?


306

मुझे यकीन है कि क्यों हम की जरूरत है नहीं कर रहा हूँ finallyमें try...except...finallyबयान। मेरी राय में, यह कोड ब्लॉक है

try:
    run_code1()
except TypeError:
    run_code2()
other_code()

यह एक का उपयोग कर के साथ ही है finally:

try:
    run_code1()
except TypeError:
    run_code2()
finally:
    other_code()

क्या मैं कुछ भूल रहा हूँ?

जवाबों:


422

यदि आप जल्दी लौटते हैं तो इससे फर्क पड़ता है:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   # The finally block is run before the method returns
finally:
    other_code()

इसकी तुलना करें:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   

other_code()  # This doesn't get run if there's an exception.

अन्य स्थितियां जो मतभेद पैदा कर सकती हैं:

  • यदि एक अपवाद को छोड़कर ब्लॉक के अंदर फेंक दिया जाता है।
  • यदि एक अपवाद फेंक दिया जाता है, run_code1()लेकिन यह नहीं है TypeError
  • अन्य नियंत्रण प्रवाह विवरण जैसे continueऔर breakकथन।

1
कोशिश करें: #x = हैलो + 20 x = 10 + 20 को छोड़कर: प्रिंट करें 'मैं' को छोड़कर ब्लॉक में हूं 'x = 20 + 30 और: प्रिंट' मैं दूसरे ब्लॉक में हूं 'x + = 1 आखिरकार: प्रिंट' अंत में x =% s '% (x)
अभिजीत साहू

89

आप finallyयह सुनिश्चित करने के लिए उपयोग कर सकते हैं कि फ़ाइलें या संसाधन बंद हैं या जारी किए गए हैं, भले ही कोई अपवाद न हो, भले ही आप अपवाद न पकड़ें। (या यदि आप उस विशिष्ट अपवाद को नहीं पकड़ते हैं।)

myfile = open("test.txt", "w")

try:
    myfile.write("the Answer is: ")
    myfile.write(42)   # raises TypeError, which will be propagated to caller
finally:
    myfile.close()     # will be executed before TypeError is propagated

इस उदाहरण में आप withकथन का उपयोग करके बेहतर होंगे , लेकिन इस प्रकार की संरचना का उपयोग अन्य प्रकार के संसाधनों के लिए किया जा सकता है।

कुछ साल बाद, मैंने एक ब्लॉग पोस्ट लिखी जिसमें दुर्व्यवहार के बारे में लिखा finallyजा सकता है कि पाठक बहुत खुश हो सकते हैं।


23

वे समकक्ष नहीं हैं। अंत में कोड चलाया जाता है और कोई बात नहीं होती है। यह सफाई कोड के लिए उपयोगी है जिसे चलाना है।


15
Finally code is run no matter what else happens... जब तक कोई अनंत लूप न हो। या एक पॉवरकट। या os._exit()। या ...
मार्क बायर्स

3
@ मार्क दरअसल, sys.exit एक सामान्य अपवाद फेंकता है। लेकिन हां, कुछ भी जो प्रक्रिया को तुरंत समाप्त करने का कारण बनता है, इसका मतलब होगा कि कुछ और निष्पादित नहीं करता है।
एंटीमनी

1
@Antimony: धन्यवाद। को बदल दिया os._exit
मार्क बायर्स

बस सोच रहा था, कि अगर कोड एक अपवाद पाया जाता है, तो सिवाय इसके कि कोड के भीतर प्रवेश कैसे होगा, क्‍यों न क्‍लीन अप कोड रखा जाए?
स्टीफन जैकब

2
@Stephen एक चीज़ के लिए, अंत में कोड तब भी चलता है, जब आप कोशिश ब्लॉक से लौटते हैं। उस स्थिति में, आप खंड को छोड़कर नहीं मारा जाएगा।
एंटिमोनी

18

ऊपर दिए गए अन्य उत्तरों में जोड़ने के लिए, finallyक्लॉज बिना किसी बात के निष्पादित करता है, जबकि elseक्लॉज केवल तभी निष्पादित होता है जब कोई अपवाद नहीं उठाया गया था।

उदाहरण के लिए, बिना किसी अपवाद के किसी फ़ाइल को लिखना निम्नलिखित आउटपुट देगा:

file = open('test.txt', 'w')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

उत्पादन:

Writing to file.
Write successful.
File closed.

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

file = open('test.txt', 'r')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

उत्पादन:

Could not write to file.
File closed.

हम देख सकते हैं कि finallyखंड अपवाद के बिना निष्पादित होता है। उम्मीद है की यह मदद करेगा।


2
यह तब भी काम करता था जब आप "अंतत:" क्लॉज़ का उपयोग नहीं करते थे, जो प्रश्न का उत्तर नहीं देता क्योंकि ओपी अंतर जानना चाहता है, एक अच्छा उदाहरण IOError की तुलना में एक अलग त्रुटि पैदा कर सकता है, यह दिखाने के लिए कि कॉल करने वाले को प्रचारित करने से पहले अंत में क्लॉज ब्लॉक निष्पादित किया जाता है।
Reda Drissi

2
मुझे नहीं पता elseथा कि यह एक चीज़ है। जानने के लिए उपयोगी।
माज़ुन्की

8

कोड ब्लॉक समकक्ष नहीं हैं। finallyखंड भी अगर चलाया जाएगा run_code1()के अलावा अन्य एक अपवाद फेंकता है TypeError, या अगर run_code2(), एक अपवाद फेंकता है, जबकि other_code()पहले संस्करण में इन मामलों में भाग नहीं किया जाएगा।


7

आपके पहले उदाहरण में, run_code1()अपवाद न होने पर क्या होता है TypeError? ...other_code() निष्पादित नहीं किया जाएगा।

उस finally:संस्करण के साथ तुलना करें : other_code()बिना किसी अपवाद के उठाए जाने की गारंटी दी जाती है।


7

जैसा कि प्रलेखन में बताया गया है , finallyक्लॉज का उद्देश्य क्लीन-अप क्रियाओं को परिभाषित करना है जिन्हें सभी परिस्थितियों में निष्पादित किया जाना चाहिए ।

यदि finallyमौजूद है, तो यह 'क्लीनअप' हैंडलर निर्दिष्ट करता है। try खंड किसी भी सहित निष्पादित किया जाता है, exceptऔर elseखंड। यदि किसी अपवाद में कोई अपवाद होता है और उसे नियंत्रित नहीं किया जाता है, तो अपवाद अस्थायी रूप से सहेज लिया जाता है। finallyखंड निष्पादित किया जाता है। यदि कोई सहेजा गया अपवाद है, तो वह finally खंड के अंत में पुन: उठाया जाता है ।

एक उदाहरण:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

जैसा कि आप देख सकते हैं, finallyकिसी भी घटना में खंड निष्पादित किया जाता है। TypeErrorदो तार विभाजित करके नहीं संभाला है द्वारा उठाए गए exceptखंड और बाद इसलिए फिर से उठायाfinally खंड मार डाला गया है।

वास्तविक दुनिया के अनुप्रयोगों में, अंतत: खंड बाहरी संसाधनों (जैसे फाइलें या नेटवर्क कनेक्शन) को जारी करने के लिए उपयोगी है, भले ही संसाधन का उपयोग सफल रहा हो।


4

सही उदाहरण नीचे दिया गया है:

try:
    #x = Hello + 20
    x = 10 + 20 
except:
    print 'I am in except block'
    x = 20 + 30
else:
    print 'I am in else block'
    x += 1
finally:
    print 'Finally x = %s' %(x)

3

finally"सफाई कार्यों" को परिभाषित करने के लिए है । finallyखंड रवाना होने से पहले किसी भी घटना में क्रियान्वित किया जाता हैtry बयान, एक अपवाद (भले ही आप इसे संभाल नहीं है) या नहीं हुआ है या नहीं।

मैं दूसरा @ बायर्स का उदाहरण।


2

अंत में तब भी उपयोग किया जा सकता है जब आप अपने मुख्य कार्य के लिए कोड चलाने से पहले "वैकल्पिक" कोड चलाना चाहते हैं और विभिन्न कारणों से वैकल्पिक कोड विफल हो सकता है।

निम्नलिखित उदाहरण में, हम ठीक से नहीं जानते कि किस प्रकार के अपवाद store_some_debug_infoफेंक सकते हैं।

हम दौड़ सकते हैं:

try:
  store_some_debug_info()
except Exception:
  pass
do_something_really_important() 

लेकिन, अधिकांश लिंटर एक अपवाद के बहुत अस्पष्ट पकड़ने के बारे में शिकायत करेंगे। इसके अलावा, चूंकि हम सिर्फ passत्रुटियों के लिए चुन रहे हैं, इसलिए exceptब्लॉक वास्तव में मूल्य नहीं जोड़ता है।

try:
  store_some_debug_info()
finally:
  do_something_really_important()     

उपरोक्त कोड का कोड के 1 ब्लॉक के समान प्रभाव है, लेकिन अधिक संक्षिप्त है।


2

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

resource = create_resource
try:
  use resource
finally:
  resource.cleanup

और संसाधन को साफ किया जाएगा चाहे आप कोशिश और अंत में क्या करें। इसके अलावा, यदि निष्पादन tryब्लॉक तक कभी नहीं पहुंचता है, तो इसे साफ नहीं किया जाएगा । (यानी create_resourceखुद एक अपवाद फेंकता है) यह आपके कोड को "अपवाद सुरक्षित" बनाता है।

जैसा कि आपको वास्तव में आखिरकार ब्लॉक की जरूरत है, सभी भाषाओं को नहीं। C ++ में जहां आपने स्वचालित रूप से डिस्ट्रक्टर्स को बुलाया है जो एक अपवाद को ढेर में अनियंत्रित होने पर सफाई लागू करता है। मुझे लगता है कि यह प्रयास करने की तुलना में क्लीनर कोड की दिशा में एक कदम है ... अंत में भाषाएं।

{    
  type object1;
  smart_pointer<type> object1(new type());
} // destructors are automagically called here in LIFO order so no finally required.

2

एक कोशिश ब्लॉक में सिर्फ एक अनिवार्य खंड होता है: कोशिश कथन। अपवाद, और अंत में क्लाज वैकल्पिक हैं और उपयोगकर्ता वरीयता पर आधारित हैं।

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


1
ये गलत है। सिवाय कथन के अनिवार्य है। - लुकास अज़ीवेदो 1 फरवरी को 12:04 पर यह गलत है, जैसा कि मैंने अभी-अभी एक ब्लॉक-एंड ब्लॉक के साथ पायथन 3.5 प्रोग्राम को संकलित किया है, जिसमें कोई "खंड" नहीं है।
रोब टो

2
मैंने स्वयं और अपने अविश्वास के लिए यह कोशिश की, सिवाय खंड खंड अनिवार्य नहीं है।
कप्तान

1

अंत में जरूरत देखने के लिए ये पायथन 3 कोड चलाएं:

मामला एक:

count = 0
while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")
        finally:
            print("Your Attempts: {}".format(count))

CASE2:

count = 0

while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")

        print("Your Attempts: {}".format(count))

हर बार निम्नलिखित इनपुट आज़माएं:

  1. यादृच्छिक पूर्णांक
  2. सही कोड जो 586 है (यह प्रयास करें और आपको अपना उत्तर मिलेगा)
  3. बेतरतीब तार

** पायथन सीखने के एक बहुत ही प्रारंभिक चरण में।


1

मैं एक कोड चलाने की कोशिश कर रहा था जहाँ मैं एक्सेल शीट पढ़ना चाहता था। मुद्दा था, अगर कोई फ़ाइल है जिसमें कोई शीट नहीं है जिसका नाम है: शीटसम मैं इसे त्रुटि स्थान पर स्थानांतरित करने में सक्षम नहीं हूं !! कोड मैंने लिखा था:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets['df_1'] = pd.read_excel(open(data_file,'rb'), 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

त्रुटि देना:

[WinError 32] प्रक्रिया फ़ाइल तक नहीं पहुँच सकती क्योंकि इसका उपयोग किसी अन्य प्रक्रिया द्वारा किया जा रहा है

मुझे पूरा try except with finallyब्लॉक जोड़ना था और finallyमुझे बताना चाहिए कि मुझे किसी भी मामले में फाइल को बंद करना होगा:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets_file = open(data_file,'rb')
        sheets['df_1'] = pd.read_excel(sheets_file, 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    finally:
        sheets_file.close()
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

अन्यथा, फ़ाइल अभी भी खुला है पृष्ठभूमि है।

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

.. यहाँ पर

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