Exception Handling in Python

কোড করতে গিয়ে অসঙ্গত অপারেশন অথবা ভুল ইনপুট ইত্যাদি নানা কারণে এক্সসেপশন / এরর আসতেই পারে। পাইথন নিজে থেকে এগুলো সল্ভ করে দিবে না। কোন একটা লাইনের এক্সেপশন আমাদের পুরো প্রোগ্রাম কে বন্ধ করে দিতে পারে। সেক্ষেত্রে, সবচেয়ে ভালো উপায় হচ্ছে সতর্কতার সাথে , সেই সব এরর / এক্সেপশন হ্যান্ডেল করার কোড লিখে রাখা। তবে , শুধু মাত্র যেসব জায়গায় এরর / এক্সেপশন আসতে পারে সেইসব জায়গায়। তাহলে , আমাদের পুরো প্রোগ্রাম বন্ধ ও হবে না এবং আমরা আমাদের ভুলগুলো ও সাথে সাথে টার্মিনাল থেকে দেখে নিতে পারবো।
 
 
Syntax
try:
    # statement_1
    # statement_2
    ...
    # statement_n
    
except:
    # execute if error occured in try block

 

যেই কোড গুলো ভুল হবার সম্ভাবনা রয়েছে সেগুলো আমরা try block এ লিখবো। ভুল হলে , প্রোগ্রামটি বন্ধ হবার পরিবর্তে পাইথনকে কি করতে হবে , সেই সমস্ত ইন্সট্রাকশন except এ লিখে দিবো। try block এ যদি কোনো এক্সেপশন / এরর না থাকে , তাহলে কখনোই except block কাজ করবে না। try block এ একটি ভুল হলেই except block কাজ করবে ।
try:
    print( 2 + 2 )
    x = 4
    print( x / 10 )
    print("Last Line")
except:
    print("Error Occured")

 

output
4
0.4
Last Line

 

উপরের উদাহরণে try block এ কোনো এক্সেপশন / এরর নেই , এজন্য except block এর লিখা প্রিন্ট হয় নি।
এখন যদি আমরা একটি ভুল করি —
try:
  print( 2 + 2 )
  x = 4
  print( x / 0 )
  print("Last Line")
except:
  print("Error Occured")

 

output
4
Error Occured

 

তাহলে দেখা যাচ্ছে 3 no. লাইন পর্যন্ত try block এ কোন সমস্যা ছিল না বলেই , try block এর 3 no. লাইন পর্যন্ত এক্সিকিউট হয়েছে। যখন 4 no. লাইনে আমরা 0 দিয়ে ভাগ দিতে চেয়েছি যেটা আসলে একটা এরর , এরজন্য এরপর থেকে আর কোন লাইন try block এ এক্সিকিউট না হয়ে , সরাসরি except এ চলে গিয়ে “Error Occured” (যেটা আমরা এ লিখেছি ) প্রিন্ট করেছে।
তবে , একটি সমস্যা আছে , আমরা টার্মিনাল দেখে বলতে পারবো না , আসলে কি ভুল হয়েছে , এজন্য এরর মেসেজটি স্পেসিফিকভাবে লিখা ভালো।
try:
  print( 2 + 2 )
  x = 4
  print( x / 0 )
  print("Last Line")
except:
  print("Error ! Can not divided by zero")

 

output
4
Error ! Can not divided by zero

 

বেশ ! কিন্তু , সবসময় এরর / এক্সসেপশন আমাদের জানার মধ্যে নাও থাকতে পারে। যেকোনো এক্সেপশন হলে কি করতে হবে , সেই মেসেজ এর দায়ভার আমরা পাইথনের উপর ছেড়ে দিতে পারি।
try:
  print( 2 + 2 )
  x = 4
  print( x / 0 )
  print("Last Line")
except Exception as e:
  print(f"Error ! {e}")

 

Exception keyword দিয়ে এক্সেপশন ধরে এর e variable এর মধ্যে স্টোর করলাম। যার ফলে , যেকোনো এক্সেপশন হোক না কেন , আমরা সেই দায়িত্ব পাইথনের হাতে ছেড়ে দিলাম। এবং পাইথন ই এরর মেসেজ জেনারেট করে দিবে।
আরেকটি বিষয় থেকে যায় সেটা হলো , ঢালাওভাবে সব এক্সেপশন হ্যান্ডেল করাটা ভালো অভ্যাস না। স্পেসিফিক এক্সসেপশন-ই আমাদের হ্যান্ডেল করা উচিত।
try:
  print( 2 + 2 )
  x = 4
  print( x / 0 )
  print("Last Line")
except ZeroDivisionError as e:
  print(f"Error : {e}")

 

সো , এভাবে এক্সেপশন গুলো ধরলে , কোডের রিডিবিলিটি ভালো থাকে।
আমরা চাইলে একটি try block এর জন্য মাল্টিপল except block রাখতে পারি। এখানে একটি বিষয় লক্ষ্যণীয় , অনেকগুলা except block থাকলেও মাত্র একটা except block কাজ করবে , এবং এর মধ্যে যেই এক্সেপশন আগে ঘটবে , তার জন্য লেখা except block কাজ করবে।
try:
  print( 2 + 2 )
  x = 4
  print( y / 0 )
  print("Last Line")
except ZeroDivisionError as e:
  print(f"Error : {e}")
except NameError as e:
  print(f"Error : {e}")

 

দেখেই বুঝতে পেরেছেন , 4 no. লাইনে ভুল করেছি। কিন্তু এখানে ভুল করেছি দুইটা-
  • y variable টি আগে কোথাও ডিফাইন করা ছাড়াই এখানে ব্যবহার করছি
  • y কে ০ দ্বারা ভাগ করছি
আবার লিখার জন্য লিখেছি আগে এবং লিখেছি পরে। কিন্তু পাইথন কোড এক্সিকিউট করার সময় আগে `y` কে পাবে , তাই NameError এক্সসেপশন ব্লকটাই কাজ করবে ।
output
4
Error : name 'y' is not defined

 

 
এই try-except ব্লক এর সাথে আরেকটা block পাইথন আমাদেরকে অতিরিক্ত দিয়ে থাকে। সেটা হচ্ছে finally block। এই block এর কাজ হচ্ছে , যে try / except যেটাই কাজ করুক না কেন , তার পরে সবার শেষে finally block কাজ করবেই।
try:
  print( 2 + 2 )
  x = 4
  print( y / 0 )
except ZeroDivisionError as e:
  print(f"Error : {e}")
except NameError as e:
  print(f"Error : {e}")
finally:
  print("I am 'finally' working...")

 

output
4
Error : name 'y' is not defined
I am 'finally' working...

 

ধরেন ,try block এ কোন ধরণের এরর / এক্সেপশন হয় নি , এবং এটার জন্য , আমরা try block এর কোন ডাটা এর উপর কোন কাজ করতে চাচ্ছি। সেটা করতে গেলে , পাইথন আমাদের কে আরো একটা block দিয়ে থাকে। সেটা হচ্ছে else block। এটা কিন্তু if-else এর else না।
try:
  print( 2 + 2 )
  x = 4
  y = x / 2
except ZeroDivisionError as e:
  print(f"Error : {e}")
except NameError as e:
  print(f"Error : {e}")
else:
  # working if try block is completely error free
  print(f"Value of y is {y}")
finally:
  print("I am 'finally' working...")

 

output
4
Value of y is 2.0
I am 'finally' working...

 

else block কাজ করতে হলে , try block এ কোন ধরণের এক্সেপশন থাকা যাবে না।
উদাহরন

উদাহরণ ১- 

try ভিতর কোন statement ভুল হলে except ভিতর যে statement গুলো থাকবে তা রান হবে কিন্তু যদি try ভিতর সব statement ঠিক থাকে তবে except ভিতর কোন statement কাজ করবে নাহ । একটি   উদাহরণ দেখা যাক

print('One')
print('Two')
try:
   print(10/0)
except ZeroDivisionError:
   print("Exception passed")
print('Four')
print('Five')

আউটপুট

One
Two
Exception passed
Four
Five

উদাহরণ ২- 

আমাদের অনেক সময় try statement আলাদা আলাদা error জন্য আলাদা আলাদা error দেখানোর জন্য multiple except blocks এর ব্যবহার করে থাকি –

try:
   x=int(input("Enter First Number: "))
   y=int(input("Enter Second Number: "))
   print(x/y)
except ZeroDivisionError:
   print("Can't Divide with Zero")
except ValueError:
   print("please provide int value only")

আউটপুট

Enter First Number: 10
Enter Second Number: 2
5.0
Enter First Number: 23
Enter Second Number: 0
Can't Divide with Zero
Enter First Number: 12
Enter Second Number: zero
please provide int value only

উদাহরণ ৩- 

আলাদা আলাদা  multiple exception না লিখে আমরা  এক লাইনে except করার জন্য আমাদের কে সাধারণত validation error কে টাপল এ মধ্যে রেখে চেক করতে হবে  –

try:
   x=int(input("Enter First Number: "))
   y=int(input("Enter Second Number: "))
   print(x/y)
except (ZeroDivisionError,ValueError) as e:
   print("Please Provide valid numbers only and problem is: ", e)

আউটপুট

Enter First Number: 10
Enter Second Number: one
Please Provide valid numbers only and problem is:  invalid literal for int() with base 10: 'one'
Enter First Number: 10
Enter Second Number: 0
Please Provide valid numbers only and problem is:  division by zero

উদাহরণ ৪- 

আমাদের অনেক সময় exist validation error check করে কোন ইরর না ধরতে পারলে তখন আমরা তা default exception দিয়ে চেক করে থাকি –

try:
   x=int(input("Enter First Number: "))
   y=int(input("Enter Second Number: "))
   print(x/y)
except ZeroDivisionError:
   print("ZeroDivisionError: Can't divide with zero")
except:
   print("Default Except: Please provide valid input only")

আউটপুট

Enter First Number: 10
Enter Second Number: 0
ZeroDivisionError: Can't divide with zero
Enter First Number: 10
Enter Second Number: zero
Default Except: Please provide valid input only

 

উদাহরণ ৫- 

আমাদের try-except এ finally নামে আর একটা keyword থাকে যা দিয়ে আমাদের try-except যেকোন statement ঠিক execute হোক না কেন finally  এর ভিতর যে statement থাকবে তা অবশ্যই রান করবে ।

try:
    x=int(input("Enter First Number: "))
    y=int(input("Enter Second Number: "))
    print(x/y)
except ZeroDivisionError:
    print("ZeroDivisionError: Can't divide with zero")
finally:
    print('Finishing up.')

আউটপুট

Enter First Number: 10
Enter Second Number: 20
0.5
Finishing up.
Enter First Number: 10
Enter Second Number: 0
ZeroDivisionError: Can't divide with zero
Finishing up.

 

এসো নিজে করি
অনুশীলনঃ
  •  এমন একটি টেক্সট ফাইল ওপেন করার চেষ্টা করুন , যেটি আপনার ডিস্কে নেই , এবং যথাযথ এরর প্রিন্ট করে দেখান ।
  • একটি ফাংশন দুইটি প্যারামিটার নেয় , এবং এর কাজ হচ্ছে ভাগফল বের করে দেয়া। ফাংশনটি এমনভাবে লিখুন যেন কখনই এরর না দেয়। (sample input: a=10,b=5 | a=”a”,b=10 | a= 10 , b= 0)
  • আপনাকে একটি অ্যারে দেওয়া হলো । আপনার কাজ হচ্ছে একটি ইনফিনিটি লুপ চালিয়ে অ্যারের সব ভ্যালু প্রিন্ট করতে কিন্তু অই ইনফিনিটি লুপ থেকে বের হবার জন্য আপনি কোন কন্ডিশনাল statement ব্যবহার করতে পারবেন নাহ ।  আবার কোড কোন ভুল দেখাবে নাহ । 
  • দুই টি ইনপুট  নিবেন এবং টার্মিনাল থেকে ইনপুট নেবার যত ধরনের লজিকাল এরর খাওয়া যায় সব গুলো এরর গুলো প্রিন্ট করবেন এবং লাস্ট বেলায় সঠিক ইনপুট নিয়ে তাদের ভাগফল দেখাবেন । যত বেশি এরর handle করতে পারবেন আপনার পয়েন্ট তত বেশি । 
  • একটি কোড লিখবেন যা দিয়ে একটি ফাইল open হবে । এখন যদি আমাদের ডেস্ক অই ফাইল থাকে তবে তা ওপেন হবে আর না থাকলে ওপেন হবে নাহ । কিন্তু আমাদের কোডের শেষবেলায় দায়িত্ব অই ফাইল টি close করা । আপনারা এই কোড টি try-exception মাধ্যমে করার চেষ্টা করবেন । 
ইন্টারভিউ প্রশ্নোত্তর
গুরুত্বপূর্ন প্রশ্নসমুহঃ 
  • কোন keyword দিয়ে আমরা এরর গুলো দেখতে পারি ?
  • কোন ব্লক দিয়ে আমরা ঝামেলাপুর্ন কোড হ্যান্ডেল করি ?
  • এরর হ্যান্ডেল করা কেন জরুরী ?
  • পাইথন এ কিছু built-in-exceptions সম্পর্কে বলেন । 
  • পাইথন এ raising an error এবং throwing an exception পার্থক্য কি ?