এরর কী?
Python-এ program চলাকালীন দুই ধরনের সমস্যা হতে পারে — Syntax Error এবং Exception। Syntax error হলো code-এ ব্যাকরণগত ভুল, যা program run করার আগেই ধরা পড়ে। আর Exception হলো program চলার সময় ঘটে যাওয়া ত্রুটি।
Syntax Error বনাম Exception
- Syntax Error — code লেখার সময় ভুল (যেমন: colon মিস করা, bracket না বন্ধ করা)। Python parser এটি ধরে ফেলে, program কখনোই run হয় না।
- Exception — code সঠিক, কিন্তু runtime-এ সমস্যা হয় (যেমন: শূন্য দিয়ে ভাগ, নেই এমন ফাইল পড়া)। এটি handle করা যায়।
# Syntax Error — program run-ই হবে না
if True
print("Hello") # SyntaxError: colon মিস!
# Exception — runtime-এ error হবে
x = 10 / 0 # ZeroDivisionError
int("abc") # ValueError
my_list[100] # IndexError
সাধারণ Exception Types
| Exception | কখন ঘটে | উদাহরণ |
|---|---|---|
ZeroDivisionError | শূন্য দিয়ে ভাগ করলে | 10 / 0 |
ValueError | ভুল মানের ডেটা দিলে | int("abc") |
TypeError | ভুল type-এ operation করলে | "2" + 3 |
IndexError | list-এ ভুল index দিলে | lst[100] |
KeyError | dictionary-তে নেই এমন key দিলে | d["xyz"] |
FileNotFoundError | নেই এমন ফাইল পড়তে চাইলে | open("x.txt") |
AttributeError | নেই এমন attribute access করলে | "hi".append() |
NameError | undefined variable ব্যবহার করলে | print(xyz) |
- Python-এ সব exceptions
BaseExceptionclass থেকে আসে - সাধারণ exceptions
Exceptionclass-এর sub-class BaseException→Exception→ValueError,TypeError,KeyErrorইত্যাদি- Error hierarchy জানলে আপনি সঠিক level-এ error catch করতে পারবেন
try-except Block
Exception handle করার মূল হাতিয়ার হলো try-except block। try block-এ সম্ভাব্য error-যুক্ত code রাখা হয়, আর except block-এ error ঘটলে কী করতে হবে তা বলা হয়:
# Basic try-except
try:
num = int(input("একটি সংখ্যা দিন: "))
result = 100 / num
print(f"ফলাফল: {result}")
except:
print("কিছু একটা ভুল হয়েছে!")
# Specific exception ধরা (recommended)
try:
num = int(input("একটি সংখ্যা দিন: "))
result = 100 / num
print(f"ফলাফল: {result}")
except ValueError:
print("দয়া করে একটি সংখ্যা দিন, অক্ষর নয়!")
except ZeroDivisionError:
print("শূন্য দিয়ে ভাগ করা যায় না!")
Exception Object ব্যবহার
as keyword দিয়ে exception object ধরে তার message দেখা যায়:
try:
f = open("data.txt", "r")
content = f.read()
except FileNotFoundError as e:
print(f"ফাইল পাওয়া যায়নি: {e}")
# Output: ফাইল পাওয়া যায়নি: [Errno 2] No such file or directory: 'data.txt'
try:
ages = {"রহিম": 25, "করিম": 30}
print(ages["জামাল"])
except KeyError as e:
print(f"এই key নেই: {e}")
# Output: এই key নেই: 'জামাল'
Multiple except ও else
একটি try block-এ একাধিক except দিয়ে বিভিন্ন ধরনের error আলাদাভাবে handle করা যায়। এছাড়া else clause দিয়ে error না হলে কী করতে হবে তাও বলা যায়:
# Multiple except + else
try:
filename = input("ফাইলের নাম: ")
with open(filename, "r") as f:
data = f.read()
number = int(data.strip())
except FileNotFoundError:
print("ফাইল পাওয়া যায়নি!")
except ValueError:
print("ফাইলে সংখ্যা নেই!")
except PermissionError:
print("ফাইল পড়ার অনুমতি নেই!")
else:
# শুধু তখনই চলবে যখন কোনো error হবে না
print(f"ফাইল থেকে পড়া সংখ্যা: {number}")
print(f"সংখ্যার বর্গ: {number ** 2}")
| Block | কখন চলে | ব্যবহার |
|---|---|---|
try | সবসময় (প্রথমে) | সম্ভাব্য error-যুক্ত code রাখুন |
except | শুধু error হলে | Error handle করুন |
else | error না হলে | সফল হলে কী করতে হবে |
finally | সবসময় (শেষে) | Cleanup code (ফাইল বন্ধ, connection close) |
একটি except-এ একাধিক Exception
# Tuple দিয়ে একাধিক exception এক except-এ ধরা
try:
value = int(input("সংখ্যা: "))
result = 100 / value
except (ValueError, ZeroDivisionError) as e:
print(f"ইনপুট সমস্যা: {e}")
# সাধারণ Exception class দিয়ে সব ধরা (শেষ resort)
try:
# কিছু uncertain code
risky_operation()
except Exception as e:
print(f"অপ্রত্যাশিত সমস্যা: {type(e).__name__}: {e}")
"TEFE" = Try → Except → Finally → Else
কিন্তু লেখার ক্রম হলো: try → except → else → finally
মনে রাখুন: "Try Except, Else Fine" — চেষ্টা করো, ব্যতিক্রম ধরো, নয়তো ভালো, এবং শেষে পরিষ্কার করো!
finally Block
finally block সবসময় চলে — error হোক বা না হোক, return statement থাকুক বা না থাকুক। এটি cleanup code-এর জন্য আদর্শ:
# finally — সবসময় চলে
try:
f = open("data.txt", "r")
data = f.read()
result = int(data)
except FileNotFoundError:
print("ফাইল নেই!")
result = 0
except ValueError:
print("ফাইলে ভুল ডেটা!")
result = 0
else:
print(f"সফলভাবে পড়া হয়েছে: {result}")
finally:
# এই block সবসময় চলবে!
print("Program শেষ হচ্ছে...")
try:
f.close()
print("ফাইল বন্ধ করা হয়েছে")
except NameError:
pass # f তৈরিই হয়নি মানে ফাইল খোলাই হয়নি
finally-এর বিশেষত্ব
- Error হলেও চলে, না হলেও চলে
returnstatement-এর পরেও চলে (function-এর ভেতরে)breakবাcontinue-এর পরেও চলে (loop-এর ভেতরে)- শুধু
os._exit()বা power failure হলে চলে না
# return-এর পরেও finally চলে!
def divide(a, b):
try:
return a / b
except ZeroDivisionError:
return "ভাগ করা যায় না"
finally:
print("divide function শেষ!") # সবসময় print হবে
print(divide(10, 2))
# Output:
# divide function শেষ!
# 5.0
- ফাইল হ্যান্ডলিং-এর জন্য
withstatement ব্যবহার করুন — এটি internallyfinallyব্যবহার করে - Database connection, network socket ইত্যাদির জন্য
finallyদিয়ে cleanup নিশ্চিত করুন try-finally(except ছাড়া) ব্যবহার করা যায় — শুধু cleanup নিশ্চিত করতে
raise Statement
raise keyword দিয়ে ইচ্ছামতো exception তৈরি (raise) করা যায়। এটি কখন দরকার? — যখন আপনি নিজে কোনো ভুল শর্ত শনাক্ত করেন এবং program-কে জানাতে চান:
# নিজে exception raise করা
def set_age(age):
if age < 0:
raise ValueError("বয়স নেতিবাচক হতে পারে না!")
if age > 150:
raise ValueError("বয়স ১৫০-এর বেশি হতে পারে না!")
return age
try:
user_age = set_age(-5)
except ValueError as e:
print(f"ভুল: {e}")
# Output: ভুল: বয়স নেতিবাচক হতে পারে না!
Re-raising Exception
কখনো কখনো exception catch করে কিছু কাজ (যেমন logging) করার পর আবার সেই exception-টিকে re-raise করতে হয়:
import logging
def process_data(data):
try:
result = int(data) * 2
return result
except ValueError:
logging.error(f"ভুল ডেটা পাওয়া গেছে: {data}")
raise # একই exception আবার raise করো
# অথবা: raise ValueError("ডেটা প্রসেস ব্যর্থ") from None
try:
process_data("abc")
except ValueError as e:
print(f"শেষ পর্যন্ত এখানে ধরা পড়লো: {e}")
| raise Pattern | কাজ | ব্যবহার |
|---|---|---|
raise ValueError("msg") | নতুন exception তৈরি | Input validation |
raise | বর্তমান exception re-raise | Logging-এর পরে |
raise X from Y | Exception chaining | মূল কারণ সংরক্ষণ |
raise X from None | Chain ছাড়া নতুন exception | মূল error লুকাতে |
Custom Exceptions
Python-এ নিজের exception class তৈরি করা যায়। এটি Exception class থেকে inherit করতে হয়। Custom exceptions ব্যবহার করলে আপনার code আরো পরিষ্কার ও সুনির্দিষ্ট হয়:
# সহজ custom exception
class InvalidAgeError(Exception):
"""বয়স সংক্রান্ত ত্রুটি।"""
pass
# বিস্তারিত custom exception
class InsufficientBalanceError(Exception):
"""ব্যালেন্স অপর্যাপ্ত হলে raise হবে।"""
def __init__(self, balance, amount):
self.balance = balance
self.amount = amount
self.deficit = amount - balance
super().__init__(
f"ব্যালেন্স অপর্যাপ্ত! বর্তমান: ৳{balance}, প্রয়োজন: ৳{amount}, ঘাটতি: ৳{self.deficit}"
)
# ব্যবহার
class BankAccount:
def __init__(self, name, balance=0):
self.name = name
self.balance = balance
def withdraw(self, amount):
if amount <= 0:
raise ValueError("পরিমাণ ধনাত্মক হতে হবে!")
if amount > self.balance:
raise InsufficientBalanceError(self.balance, amount)
self.balance -= amount
return self.balance
# ব্যবহার
try:
acc = BankAccount("রহিম", 1000)
acc.withdraw(1500)
except InsufficientBalanceError as e:
print(f"ত্রুটি: {e}")
print(f"ঘাটতি: ৳{e.deficit}")
except ValueError as e:
print(f"ভুল: {e}")
Exception Hierarchy তৈরি করা
# একটি project-এর জন্য exception hierarchy
class AppError(Exception):
"""Base exception — সব app error এখান থেকে আসবে।"""
pass
class DatabaseError(AppError):
"""Database সংক্রান্ত সমস্যা।"""
pass
class AuthenticationError(AppError):
"""Login/auth সমস্যা।"""
pass
class PermissionDeniedError(AuthenticationError):
"""অনুমতি নেই।"""
pass
# এখন AppError ধরলে সব ধরা পড়বে
try:
raise PermissionDeniedError("Admin access প্রয়োজন")
except AuthenticationError as e:
print(f"Auth সমস্যা: {e}") # এটি ধরবে কারণ PermissionDenied হলো AuthenticationError-এর child
- সবসময়
Exception(বা তার sub-class) থেকে inherit করুন,BaseExceptionথেকে নয় - Exception class-এর নাম Error দিয়ে শেষ করুন (যেমন:
InvalidAgeError) - বড় project-এ একটি base exception তৈরি করে বাকি সব তা থেকে inherit করুন
__init__-এ extra attributes রাখলে error debugging সহজ হয়
"SERF-C" = Specific except → Else block → Raise when needed → Finally cleanup → Custom classes
নিয়ম: সবসময় specific exception ধরুন, bare except: ব্যবহার করবেন না। Exception as e ব্যবহার করে error message দেখুন। কখনোই error গিলে ফেলবেন না (except: pass করবেন না)!