Exception Handling: try/except/finally

এক্সসেপশন হ্যান্ডলিং — সুন্দরভাবে fail করা

Read: ~30 min Intermediate 5 practice problems Live code runner

1. Errors Are Expected

Real programs talk to networks, disks, users, and time — all of which fail. Python uses exceptions to signal "something unexpected just happened." If uncaught, the program crashes with a traceback. Your job is to catch the ones you can meaningfully handle and let the rest propagate upward — loudly.

বাস্তব প্রোগ্রাম network, disk, user এবং সময়ের সাথে কাজ করে — এর যেকোনোটি fail করতে পারে। Python এই ধরনের অপ্রত্যাশিত পরিস্থিতিকে exception হিসেবে signal দেয়। সঠিকভাবে handle না করলে প্রোগ্রাম traceback সহ ক্র্যাশ করে।

2. The try / except Block

safe_divide.py
def safe_divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return float("inf")
    except TypeError as e:
        print(f"bad types: {e}")
        return None

print(safe_divide(10, 2))
print(safe_divide(10, 0))
print(safe_divide("10", 2))
try block-এর code-এ exception হলে Python মিলে যাওয়া প্রথম except block-এ ঢোকে। কখনও "bare except" (except:) লিখবেন না — এটি keyboard interrupt-সহ সব কিছু চুপচাপ গিলে ফেলে।

3. The Exception Hierarchy

Every exception is a class, and they form a tree rooted at BaseException. Most user code should catch Exception or a more specific subclass — never BaseException.

প্রতিটি exception একটি class। এগুলো BaseException-এ rooted একটি গাছ তৈরি করে। সাধারণ কোড-এ Exception বা তার subclass catch করুন — BaseException কখনো নয়।
BaseException SystemExit Exception KeyboardInterrupt ArithmeticError LookupError ValueError OSError ZeroDivisionError KeyError IndexError FileNotFoundError Figure 24.1 — Python-এর exception hierarchy-র একটি অংশ।

4. else and finally

else runs only if no exception occurred; finally runs always — success, exception, or return — perfect for cleanup.

else block চলে শুধু তখনই যখন কোনো exception হয়নি। finally block সবসময় চলে — success, exception বা return, সবক্ষেত্রেই। Cleanup-এর জন্য উপযুক্ত।
full_try.py
def parse_int(s):
    try:
        n = int(s)
    except ValueError:
        print(f"not a number: {s!r}")
        return None
    else:
        print(f"parsed {n}")
        return n
    finally:
        print("— parse attempt done —")

parse_int("42")
parse_int("hello")

5. Raising and Custom Exceptions

Use raise to signal your own errors. Create a tiny subclass of Exception when the built-in names don't capture your domain.

নিজস্ব error signal দিতে raise ব্যবহার করুন। Built-in exception যথেষ্ট না হলে Exception-এর একটি ছোট subclass তৈরি করুন।
custom_err.py
class InvalidAgeError(Exception):
    """Raised when an age is outside the allowed range."""

def set_age(age):
    if not isinstance(age, int):
        raise TypeError("age must be an int")
    if age < 0 or age > 150:
        raise InvalidAgeError(f"age {age} is unrealistic")
    return age

for a in [25, -3, 200]:
    try:
        print("ok", set_age(a))
    except InvalidAgeError as e:
        print("rejected:", e)

6. EAFP vs LBYL

✅ EAFP — Easier to Ask Forgiveness (Pythonic)

  • Try the operation, handle the error if it fails
  • No race conditions between check and action
  • try: d["x"] except KeyError: ...

⚠️ LBYL — Look Before You Leap

  • Check preconditions, then act
  • State may change between check and action (race)
  • if "x" in d: d["x"]
Python's preference — EAFP। Python community সাধারণভাবে প্রথমে চেষ্টা করে exception ধরে fix করাকে বেশি পছন্দ করে।

7. Vocabulary

TermMeaningবাংলায়
ExceptionObject raised to signal an abnormal condition.অস্বাভাবিক পরিস্থিতি জানাতে raise করা object।
TracebackThe printed stack of where an exception came from.Exception কোথা থেকে এসেছে তার stack প্রিন্ট।
raiseManually trigger an exception.Manually একটি exception ঘটায়।
Re-raiseCatch, do something, then raise with no argument.Catch করে কিছু করে আবার raise করা।
EAFPTry first, handle failure.প্রথমে চেষ্টা, fail হলে handle।
LBYLCheck first, then act.আগে check, পরে action।

8. Practice Problems

  1. Wrap int(input())-like parsing of a variable in try/except. Use the string "42x".
    একটি variable-এর int() parsing কে try/except-এ wrap করুন (string: "42x")।
    ✨ Show Answer
    ans1.py
    raw = "42x"
    try:
        n = int(raw)
        print("ok:", n)
    except ValueError as e:
        print("could not parse:", e)
  2. Write a NegativeNumberError custom exception and a sqrt_safe(x) that raises it for negative input.
    কাস্টম NegativeNumberError তৈরি করুন এবং sqrt_safe(x) লিখুন যা নেগেটিভ x-এ সেটি raise করবে।
    ✨ Show Answer
    ans2.py
    class NegativeNumberError(Exception): pass
    
    def sqrt_safe(x):
        if x < 0:
            raise NegativeNumberError(f"cannot sqrt {x}")
        return x ** 0.5
    
    for v in [9, -4]:
        try:
            print(sqrt_safe(v))
        except NegativeNumberError as e:
            print("error:", e)
  3. Why should you avoid a bare except: clause?
    Bare except: কেন এড়াতে হবে?
    ✨ Show Answer

    Answer: It catches everything — including KeyboardInterrupt and SystemExit — which makes programs impossible to stop with Ctrl+C and hides bugs you would have wanted to see. Catch Exception at most, preferably a specific subclass.

    এটি KeyboardInterrupt-সহ সবকিছু catch করে, ফলে Ctrl+C-তেও প্রোগ্রাম বন্ধ হয় না এবং বাগ লুকিয়ে যায়। নির্দিষ্ট class ধরুন, বেশির ভাগ ক্ষেত্রে Exception।

  4. Use try/finally to ensure a "closing resource" message prints even when an exception occurs.
    try/finally দিয়ে নিশ্চিত করুন যে exception হলেও একটি "closing resource" বার্তা প্রিন্ট হবে।
    ✨ Show Answer
    ans4.py
    def work(fail):
        try:
            if fail:
                raise RuntimeError("boom")
            print("did work")
        finally:
            print("closing resource")
    
    work(False)
    try:
        work(True)
    except RuntimeError as e:
        print("caught:", e)
  5. Explain in one sentence what the EAFP principle is.
    এক বাক্যে EAFP নীতি ব্যাখ্যা করুন।
    ✨ Show Answer

    Answer: Easier to Ask Forgiveness than Permission — try the action first and handle the exception if it fails, rather than checking every precondition up-front.

    Easier to Ask Forgiveness than Permission — আগে চেক না করে সরাসরি চেষ্টা করুন; fail হলে exception catch করে ব্যবস্থা নিন।

Summary — Module 24

try runs risky code; except catches specific exceptions; else runs on success; finally runs always. Exceptions form a class hierarchy — catch narrowly. Raise your own subclasses of Exception when the domain calls for it. Follow the Pythonic EAFP style: try first, handle failure second.

try-এ ঝুঁকিপূর্ণ code, except-এ নির্দিষ্ট exception, else সফল হলে, finally সবসময়। Exception-গুলো class hierarchy তৈরি করে। প্রয়োজনে নিজের subclass তৈরি করুন এবং EAFP নীতি অনুসরণ করুন।

Next Module → Standard Library Tour।