পাইথনের "অবশেষে" ধারাটি আমাদের কেন দরকার?


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
@ সংস্থান: ধন্যবাদ পরিবর্তিত হয়েছে os._exit
মার্ক বাইয়ার্স

শুধু ভাবছি, কেন ব্যর্থতার সন্ধান ব্যতীত কোডটি প্রবেশ করবে যদি ব্যতীত ক্লিন আপ কোডটি কেন রেখে দেওয়া যায় না?
স্টিফেন জ্যাকব

2
@ স্টেফেন একটি জিনিসের জন্য, অবশেষে কোডটি চালিত হয় এমনকি যদি আপনি চেষ্টা ব্লক থেকে ফিরে আসেন। সেক্ষেত্রে আপনি ক্লজ বাদ দিয়ে আঘাত করবেন না।
অ্যান্টিমনি

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
এমনকি যদি আপনি "অবশেষে" ধারাটি ব্যবহার না করেন যা প্রশ্নের উত্তর দেয় না যেহেতু ওপি পার্থক্যটি জানতে চায়, একটি ভাল উদাহরণটি আইওআরারের চেয়ে আলাদা ত্রুটি ঘটায়, তা দেখানোর জন্য অবশেষে কলারটির কাছে ব্যতিক্রম প্রচারের আগে ক্লজ ব্লক কার্যকর করা হয়।
রেদা ড্রিসি

2
আমি জানতাম না elseএকটা জিনিস ছিল। জানার জন্য দরকারী।
mazunki

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

আপনার মূল কাজের জন্য কোড চালানোর আগে আপনি যখন "alচ্ছিক" কোড চালাতে চান এবং শেষ পর্যন্ত optionচ্ছিক কোডটি বিভিন্ন কারণে ব্যর্থ হতে পারে তখন অবশেষে এটিও ব্যবহার করা যেতে পারে।

নিম্নলিখিত উদাহরণে, আমরা কি ধরণের ব্যতিক্রমগুলি 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নিজেই একটি ব্যতিক্রম ছোঁড়ে) এটি আপনার কোডটিকে "ব্যতিক্রম নিরাপদ" করে তোলে।

আপনার আসলে শেষ অবধি প্রয়োজন কেন, সমস্ত ভাষা তা করে না। সি ++ এ যেখানে আপনি স্বয়ংক্রিয়ভাবে এমন ডেস্ট্রাক্টরদের ডেকে পাঠিয়েছেন যা কোনও ব্যতিক্রম স্ট্যাকটিকে তালিকাভুক্ত না করলে ক্লিনআপ প্রয়োগ করে। আমি মনে করি চেষ্টা করার সাথে তুলনা করে ক্লিনার কোডের দিকে এটি এক ধাপ… শেষ পর্যন্ত ভাষাগুলি।

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

2

একটি চেষ্টা ব্লকের একটি মাত্র বাধ্যতামূলক ধারা রয়েছে: চেষ্টা বিবৃতি। বাদে অন্য এবং অবশেষে ধারাগুলি চ্ছিক এবং ব্যবহারকারীর পছন্দের উপর ভিত্তি করে।

শেষ অবধি: পাইথন চেষ্টা স্টেটমেন্টটি ছাড়ার আগে, এটি প্রোগ্রামটি শেষ হলেও, এটি কোনও শর্তে শেষ অবধি ব্লক কোডটি চালাবে। উদাহরণস্বরূপ, যদি পাইথন বাদে বা অন্য কোনও ব্লক কোড চলাকালীন একটি ত্রুটিতে চলে যায় তবে প্রোগ্রামটি বন্ধ করার আগে অবশেষে ব্লকটি কার্যকর করা হবে।


1
এটা ভুল. বিবৃতি বাদে বাধ্যতামূলক is - লুকাস আজেভেদো 1 ফেব্রুয়ারি 12:04 এ ভুল, কারণ আমি স্রেফ একটি পাইথন ৩.৩ প্রোগ্রাম সংকলন করেছি এবং শেষ পর্যন্ত একটি ব্লক দিয়ে একটি পাইথন run.৩ প্রোগ্রাম চালিত করেছি, "ব্যতীত" ধারা ছাড়াই।
রব টু

2
আমি নিজেই এটি চেষ্টা করেছি এবং আমার অবিশ্বাসের জন্য, বাদে ধারাটি বাধ্যতামূলক নয়।
অধিনায়কব্ল্যাক

1

শেষ পর্যন্ত এর প্রয়োজনীয়তা দেখতে এই পাইথন 3 কোডগুলি চালান:

মামলা 1:

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ধারাটি যদি অন্য কোনও ব্যতিক্রম উত্থাপন করে তবে সংরক্ষিত ব্যতিক্রমটি নতুন ব্যতিক্রমের প্রসঙ্গ হিসাবে সেট করা আছে।

..More এখানে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.