এরর হ্যান্ডলিং #
ইতিপূর্বে আমরা দেখে এসেছি নানা সময়ে নানা কারণে পাইথন নানা প্রকার এরর থ্রো করতেছে। ঐসব এরর আমাদের জিন্দেগী তামা-তামা কইরা দিছে। এখন আমরা ঐসব এরর হ্যান্ডেল করার জাদুমন্ত্র শিখব। তবে তার আগে এক নজরে আমরা গুরুত্বপূর্ণ স্টান্ডার্ড এক্সেপশনগুলো দেখে নেব। আর দেখব কখন তারা রেইজ (raise) হয়।
এক্সেপশন | বর্ণনা |
---|---|
FileNotFoundError | যখন কোন নির্দিষ্ট ফাইলের অস্তিত্ব খুঁজে পাওয়া যায় না তখন রেইজ হয়। |
ImportError | যখন import স্টেটমেন্ট ফেল করে তখন রেইজ হয়। |
IndentationError | যখন কোডব্লকে ইনডেন্টেশন মেইনটেইন করা হয় না ঠিকমত তখন রেইজ হয়। |
IndexError | যখন কোন সিকুয়েন্সে কোন নির্দিষ্ট ইনডেক্স খুঁজে পাওয়া যায় না তখন রেইজ হয়। |
KeyboardInterrupt | যখন Ctrl + C চেপে ইউজার কোন প্রোগ্রামের এক্সিকিউশন থামিয়ে দেয় তখন রেইজ হয়। |
KeyError | যখন ডিকশনারিতে কোন নির্দিষ্ট কী খুঁজে পাওয়া যায় না তখন রেইজ হয়। |
NameError | যখন নির্দিষ্ট কোন লোকাল বা গ্লোবাল ভ্যারিয়েবল খুঁজে পাওয়া যায় না তখন রেইজ হয়। |
OSError | যখন কোন সিস্টেম ফাংশন সিস্টেম রিলেটেড কোন এরর রিটার্ন করে তখন রেইজ হয়। |
RuntimeError | যখন কোন এরর হ্যান্ডেল করার জন্য জেনারেল কোন স্টান্ডার্ড এক্সেপশন পাওয়া যায় না তখন রেইজ হয়। |
StopIteration | যখন next() মেথড আর কোন অবজেক্টকে পয়েন্ট করে না তখন রেইজ হয়। |
SyntaxError | যখন সিনট্যাক্সে ঘাপলা থাকে তখন রেইজ হয়। |
SystemError | যখন পাইথন ইন্টারপ্রিটার কোন ইন্টারনাল এরর খুঁজে পায় তখন রেইজ হয়। |
TabError | যখন কোডে একই সাথে ট্যাব আর স্পেস দিয়ে ইন্ডেন্টেশন করা হয় তখন রেইজ হয়। |
TypeError | যখন কোন ফাংশন বা অপারেশন কোন অসঙ্গত টাইপের অবজেক্টে অ্যাপ্লাই করা হয় তখন রেইজ হয়। |
UnboundLocalError | এটা হল NameError এর শিষ্য। যখন কোন ফাংশন বা মেথডে কোন লোকাল ভ্যারিয়েবল ব্যবহার করা হয় কিন্তু ঐ ভ্যারিয়েবলের কোন ভ্যালু থাকে না তখন রেইজ হয়। |
ValueError | যখন কোন বিল্ট-ইন অপারেশন বা ফাংশন এমন কোন আর্গুমেন্ট গ্রহণ করে যার টাইপ ঠিক থাকলেও ভ্যালুতে গন্ডগোল এবং IndexError দিয়ে এই সমস্যা ধামাচাপা দেয়া যায় না তখন রেইজ হয়। |
WindowsError | উইন্ডোজ অপারেটিং সিস্টেম ঘটিত সমস্যায় রেইজ হয়। |
ZeroDivisionError | যখন কোন ভ্যালুকে শুন্য দিয়ে ভাগ করার চেষ্টা করা হয় তখন রেইজ হয়। |
এক্সেপশন (Exception) কি? #
সহজ কথায়, এক্সেপশন হল একটা ঘটনা যা প্রোগ্রাম চলার সময় কোন সমস্যার উদগীরণ হলে ঘটে। একটা উদাহরণ দিয়ে বিষয়টা আরো পরিষ্কার করে তুলে ধরা যাক। ফাইল চাপ্টারে আমরা সবার শেষে যে প্রোগ্রামটা লিখেছিলাম সেটা আবার চালাব আমরা। তবে এবার test.txt ফাইলটা ঐ জায়গা থেকে ডিলিট করে দেয়ার পর।
with open('test.txt', 'r') as my_file:
content = my_file.read()
print(content)
আউটপুট
Traceback (most recent call last):
File "/home/ugcoder/Desktop/test.py", line 1, in <module>
with open('test.txt', 'r') as my_file:
FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'
test.txt ফাইলটা না পেয়ে FileNotFoundError থ্রো করেছে পাইথন, তারপর প্রোগ্রামের এক্সিকিউশন বন্ধ হয়ে গেছে। ফলে শেষের নির্ভেজাল স্টেটমেন্টটাও এক্সিকিউট হয় নাই। এইরকম সমস্যার নিরসন করতেই এক্সেপশন হ্যান্ডলিং বা এরর হ্যান্ডলিং।
try … except #
উপরের এররটাই এবার আমরা হ্যান্ডেল করব। আগে আমরা প্রোগ্রামটা দেখব তারপর ব্যাখ্যায় যাব।
try:
with open('test.txt', 'r') as my_file:
content = my_file.read()
print(content)
except:
print('The file does not exist.')
print('Made by Maateen.')
আউটপুট
The file does not exist.
Made by Maateen.
এবার কিন্তু আর প্রোগ্রামটা ঠুস করেই শেষ হয়ে যায়নি। এররটা হ্যান্ডেল হয়ে শেষ স্টেটমেন্ট অবধি সুন্দরভাবে প্রোগ্রাম এক্সিকিউট হয়েছে।
try...except
এর ব্যাপারটা হল এরকম: নরমাল কোডগুলো try
ব্লকের ভিতর থাকবে। আর কোন এক্সেপশন রেইজ হলে except
ব্লকের কোড এক্সিকিউট হবে। কোন নির্দিষ্ট এক্সেপশন হ্যান্ডেল করার জন্য কোড লিখতে চাইলে except
এর পরে স্পেস দিয়ে এক্সেপশনের নাম দিয়ে দিতে হয়। আবার চাইলে এক্সেপশনের থ্রো করা মেসেজ হোল্ড করে প্রিন্ট করে ইউজারকে দেখানোও যায়। একটা উদাহরণ দেখা যাক।
try:
with open('test.txt', 'r') as my_file:
content = my_file.read()
print(content)
except FileNotFoundError:
print('The file does not exist.')
print('Made by Maateen.')
try:
my_list = []
print(my_list[0])
except IndexError as e:
print(e)
আউটপুট
The file does not exist.
Made by Maateen.
list index out of range
এখানে আমরা এক্সেপশনের নাম ধরে এরর হ্যান্ডেল করেছি। শেষের এক্সেপশনে পাইথনের জেনারেট করা এরর মেসেজই প্রিন্ট করে দিয়েছি। আচ্ছা, একটা try
ব্লকের কোডে কয়েকটা এরর হতে পারে। সেক্ষেত্রে কিভাবে এরর হ্যান্ডেল করব আমরা?
আসলে একটা try
ব্লকের জন্য যত খুশি তত except
ব্লক লেখা যায়। তবে প্রতিটা except
ব্লকে এক্সেপশনের নাম উল্লেখ করতে হবে। একটা নির্দিষ্ট এক্সেপশন রেইজ হলেই কেবল ঐ নির্দিষ্ট except
ব্লক এক্সিকিউট হবে। একটা উদাহরণ দেখা যাক।
try:
my_file = open('test.txt')
content = my_file.read()
i = int(content.strip())
except IOError as e:
errno, strerror = e.args
print("I/O error({0}): {1}".format(errno,strerror))
except ValueError:
print("No valid integer in line.")
except:
print("Unexpected error!")
আউটপুট
I/O error(2): No such file or directory
এখানে আমরা একটা try
ব্লকের জন্য তিনটা except
ব্লক লিখেছি। প্রথমটা IOError
এর জন্য, দ্বিতীয়টা ValueError
এর জন্য আর শেষেরটা ঐ দুইটা বাদে যেকোন এররের জন্য। এ ধরনের except
কে পাইথনিক ভাষায় Bare Except বলা হয়। বাংলায় অবশ্য আমরা এর একটা নাম দিতে পারি - ল্যাংটা এক্সেপ্ট। আর পারতপক্ষে ল্যাংটা এক্সেপ্ট স্কিপ করা উচিত আমাদের। কারণ, বেয়ার এক্সেপ্ট সব ধরনের এররকে হাইড করে দেয় ফলে আমরা জানতেই পারব না ঠিক কোন এক্সেপশনটাকে আমরা ক্যাচ করছি। তাই দেশ ও জাতির বৃহত্তর কল্যাণের স্বার্থে আমরা সবসময় এক্সেপশনের নাম উল্লেখ করে এরর হ্যান্ডেল করব।
আমরা চাইলে সবগুলো এররকে একটা except
ব্লকে সেটেল করে দিতে পারতাম।
try:
my_file = open('test.txt')
content = my_file.read()
i = int(content.strip())
except (IOError, ValueError):
pass
try … except … else #
else
ব্লক except
ব্লকের শেষে বসে। try
ব্লকে কোন এক্সেপশন রেইজ না হলেই কেবল else
ব্লকের কোড এক্সিকিউট হয়। একটা উদাহরণ দেখা যাক।
try:
a = 5
b = 8
print(a + b)
except ValueError as e:
print(e)
else:
print('There is no exception.')
আউটপুট
13
There is no exception.
কোন এক্সেপশন রেইজ হয়নি। তাই else
ব্লকের কোড এক্সিকিউট হয়েছে।
try … except … finally #
finally
ব্লক একেবারে শেষে বসে। আর কোন এক্সেপশন রেইজ হোক আর নাই বা হোক, finally
ব্লকের কোড ঠিকই এক্সিকিউট হয়। এজন্য একে ক্লীন-আপ অ্যাকশন বলা হয়। একটা উদাহরণ দেখা যাক।
try:
with open('test.txt', 'r') as my_file:
content = my_file.read()
print(content)
except FileNotFoundError:
print('The file does not exist.')
finally:
print('To be or not to be that is the question.')
আউটপুট
The file does not exist.
To be or not to be that is the question.
test.txt ফাইলটা না থাকায় FileNotFoundError
এক্সেপশন রেইজ হয়েছে। কিন্তু তারপরও finally
ব্লকের কোড ঠিকই রেইজ হয়েছে।
রেইজ এক্সেপশন #
পাইথনে তো অনেক বিল্ট-ইন এক্সেপশন আছে। আমরা চাইলে এদেরকে নিজ থেকে রেইজ করতে পারি।
try:
raise NameError('Hey! It is a custom error message.')
except NameError as e:
print(e)
আউটপুট
Hey! It is a custom error message.
এক্সেপশন রেইজ করার জন্য raise
স্টেটমেন্ট ব্যবহার করতে হয়। raise
এর পরে বিল্ট-ইন এক্সেপশনের নাম দিয়ে এর সাথেই ব্রাকেটের ভিতর এরর মেসেজ স্ট্রিং হিসাবে পাস করতে হয়।
বিল্ট-ইন এক্সেপশন ছাড়াও পাইথনে ইউজার-ডিফাইন্ড এক্সেশন ব্যবহার করা যায়। কিন্তু আমরা তো এখনও ছোট। তাই এখনই আমরা এটা শিখব না। ক্লাস, অবজেক্ট, মেথড সম্পর্কে যখন আমাদের ধারণা পরিষ্কার হবে তখন আমরা ইউজার-ডিফাইন্ড এক্সেপশন পয়দা করব। ততক্ষণ হ্যাপি এরর হ্যান্ডলিং!