এরর হ্যান্ডলিং

এরর হ্যান্ডলিং #

ইতিপূর্বে আমরা দেখে এসেছি নানা সময়ে নানা কারণে পাইথন নানা প্রকার এরর থ্রো করতেছে। ঐসব এরর আমাদের জিন্দেগী তামা-তামা কইরা দিছে। এখন আমরা ঐসব এরর হ্যান্ডেল করার জাদুমন্ত্র শিখব। তবে তার আগে এক নজরে আমরা গুরুত্বপূর্ণ স্টান্ডার্ড এক্সেপশনগুলো দেখে নেব। আর দেখব কখন তারা রেইজ (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 এর পরে বিল্ট-ইন এক্সেপশনের নাম দিয়ে এর সাথেই ব্রাকেটের ভিতর এরর মেসেজ স্ট্রিং হিসাবে পাস করতে হয়।

বিল্ট-ইন এক্সেপশন ছাড়াও পাইথনে ইউজার-ডিফাইন্ড এক্সেশন ব্যবহার করা যায়। কিন্তু আমরা তো এখনও ছোট। তাই এখনই আমরা এটা শিখব না। ক্লাস, অবজেক্ট, মেথড সম্পর্কে যখন আমাদের ধারণা পরিষ্কার হবে তখন আমরা ইউজার-ডিফাইন্ড এক্সেপশন পয়দা করব। ততক্ষণ হ্যাপি এরর হ্যান্ডলিং!

মন্তব্য করুন