Error Handling
Level: 8 | Version: v1.0 | Author: Meptrasoft
Programs receive bad input, missing files, and failed network calls. Error handling lets a program respond to problems instead of crashing. This module uses a Payment Processing System as the running example.
Exceptions Basics
An exception is an error that occurs while a program is running. When an exception occurs and is not handled, the program stops and shows an error message called a traceback.
amount = 100
result = amount / 0
Output:
ZeroDivisionError: division by zero
The program stops normal execution at that line. The lines after it do not run.
Error vs Exception
Syntax Error → Code is written incorrectly (caught before running)
Exception → Code is valid but fails while running
Syntax error (program does not even start):
if amount > 0
print("Valid")
Exception (program starts, then fails):
amount = int("abc") # ValueError at runtime
Common Exceptions
| Exception | When It Happens |
|---|---|
ZeroDivisionError |
Dividing by zero |
ValueError |
Right type, wrong value (int("abc")) |
TypeError |
Wrong type used in an operation |
IndexError |
List index out of range |
KeyError |
Dictionary key does not exist |
FileNotFoundError |
Opening a file that does not exist |
NameError |
Using a variable that was never defined |
AttributeError |
Using a method/attribute an object lacks |
numbers = [10, 20, 30]
print(numbers[5]) # IndexError
student = {"name": "Arun"}
print(student["cgpa"]) # KeyError
Output:
EXCEPTION → RUNTIME ERROR → PROGRAM STOPS (unless handled)
try / except Blocks
try
Put risky code inside a try block. Python watches it for exceptions.
try:
amount = int(input("Enter amount: "))
print("Amount:", amount)
If the risky line fails, Python stops running the try block and jumps to
except instead of crashing.
except
The except block runs only when an exception occurs in the try block.
try:
amount = int("abc")
except ValueError:
print("Invalid amount entered")
Output:
Invalid amount entered
The program continues normally after handling the error.
Catching Specific Exceptions
Handle different errors differently by naming each one:
amount = int("abc")
try:
result = amount / divisor
except ZeroDivisionError:
print("Cannot divide by zero")
except ValueError:
print("Invalid value")
Prefer specific exceptions over a bare except:, which hides real bugs.
Accessing the Error Message
Use as to capture the exception object.
try:
amount = int("abc")
except ValueError as e:
print("Error:", e)
Output:
Error: invalid literal for int() with base 10: 'abc'
else
The else block runs only when no exception occurs in the try block.
try:
amount = int("500")
except ValueError:
print("Invalid amount")
else:
print("Payment of", amount, "accepted")
Output:
Payment of 500 accepted
try succeeds → else runs
try fails → except runs, else is skipped
finally
The finally block runs always — whether an exception occurred or not. Use
it for cleanup such as closing files, closing connections, or ending a transaction.
connection_open = False
try:
connection_open = True
print("Processing payment")
except RuntimeError:
print("Payment failed")
finally:
if connection_open:
print("Closing connection")
finally runs even if try succeeds, even if except runs, and even if the
function returns from inside try.
Full Structure
try:
# risky code
except SomeError:
# runs if that error occurs
else:
# runs if no error occurs
finally:
# runs always
| Block | Runs When |
|---|---|
try |
Always (contains the risky code) |
except |
An exception occurs |
else |
No exception occurs |
finally |
Always (cleanup) |
Raising & Custom
Raising Exceptions
Use raise to trigger an exception yourself — useful for rejecting invalid data.
def process_payment(amount):
if amount <= 0:
raise ValueError("Amount must be positive")
print("Processing:", amount)
process_payment(-50)
Output:
ValueError: Amount must be positive
raise stops the function immediately, exactly like a built-in exception. The
caller can catch it:
def process_payment(amount):
try:
process_payment(-50)
except ValueError as e:
print("Rejected:", e)
Output:
raise → TRIGGER AN EXCEPTION ON PURPOSE
Custom Exceptions
Create your own exception type by inheriting from Exception. This makes errors
meaningful and specific to your application.
class PaymentError(Exception):
pass
def process_payment(amount, balance):
if amount > balance:
raise PaymentError("Insufficient balance")
print("Payment successful")
try:
process_payment(1000, 500)
except PaymentError as e:
print("Payment failed:", e)
Output:
Payment failed: Insufficient balance
A custom exception reads clearly and can be caught separately from built-in errors.
class MyError(Exception): pass → APP-SPECIFIC ERROR TYPE
assert Statement
assert checks that a condition is true. If it is false, Python raises an
AssertionError. It is used to catch programming mistakes during
development and testing.
def apply_discount(price, discount):
assert discount >= 0, "Discount cannot be negative"
return price - discount
apply_discount(100, -10)
Output:
AssertionError: Discount cannot be negative
assert condition, "message"
condition True → continue
condition False → AssertionError
Do not use assert for normal user-input validation — assertions can be
disabled when Python runs optimized (python -O). Use raise for real
validation, assert for internal sanity checks.
Complete Payment Processing Example
This combines every concept — validate with raise, a custom exception, and
try / except / else / finally in one flow.
class PaymentError(Exception):
pass
def process_payment(amount, balance):
if amount <= 0:
raise ValueError("Amount must be positive")
if amount > balance:
raise PaymentError("Insufficient balance")
return balance - amount
def pay(amount, balance):
try:
new_balance = process_payment(amount, balance)
except ValueError as e:
print("Invalid payment:", e)
except PaymentError as e:
print("Payment failed:", e)
else:
print("Payment successful. New balance:", new_balance)
finally:
print("Transaction closed\n")
pay(500, 1000) # success
pay(-50, 1000) # invalid amount
pay(2000, 1000) # insufficient balance
Output:
Payment successful. New balance: 500
Transaction closed
Invalid payment: Amount must be positive
Transaction closed
Payment failed: Insufficient balance
Transaction closed
Flow for each call:
process_payment()
↓
amount <= 0? → raise ValueError → except ValueError
amount > balance? → raise PaymentError → except PaymentError
otherwise → return balance → else block
↓
finally always runs
Each error path is handled cleanly, and finally closes the transaction every
time — success or failure.
Common Fresher Mistakes
| ✗ Mistake | Problem | ✓ Correct Understanding |
|---|---|---|
Using bare except: |
Hides real bugs | Catch specific exceptions |
| Confusing syntax error and exception | Different stages | Syntax = before run, exception = at run |
Expecting else to run after an error |
else runs only on success |
Use except for the error path |
Forgetting finally always runs |
Cleanup skipped | Put cleanup in finally |
Using assert for user validation |
Assertions can be disabled | Use raise for real validation |
Catching an exception but ignoring it (pass) |
Errors silently swallowed | Log or handle it meaningfully |
Placement Quick Points
- An exception is a runtime error; unhandled, it stops normal program execution.
- A syntax error is caught before running; an exception occurs while running.
tryholds risky code;excepthandles the error.- Catch specific exceptions, not a bare
except:. elseruns only when no exception occurs.finallyalways runs — used for cleanup.raisetriggers an exception on purpose.- Custom exceptions inherit from
Exception. assertchecks internal assumptions and raisesAssertionErroron failure.- Use
raisefor validation; useassertfor development-time checks.
Interview Questions
- What is an exception?
- An error that occurs while a program is running.
- What is the difference between a syntax error and an exception?
- A syntax error is detected before the program runs. An exception occurs during execution.
- What is the purpose of
tryandexcept? tryholds code that might fail;excepthandles the error if it occurs.- When does the
elseblock run? - Only when no exception occurs in the
tryblock. - When does the
finallyblock run? - Always — whether or not an exception occurred.
- What does
raisedo? - It triggers an exception intentionally.
- How do you create a custom exception?
- Define a class that inherits from
Exception. - What does
assertdo? - It checks a condition and raises
AssertionErrorif the condition is false. - What is the difference between
assertandraise? assertis for development-time checks and can be disabled.raiseis for real error handling and always runs.- Why avoid a bare
except:? - It catches every error, including bugs, and hides real problems.
Practice
- Trigger and read a
ZeroDivisionError. - Handle a
ValueErrorfromint("abc")usingtry/except. - Catch two different exceptions with separate
exceptblocks. - Print the error message using
except ... as e. - Add an
elseblock that runs on success. - Add a
finallyblock for cleanup. - Raise a
ValueErrorfor a negative payment amount. - Catch the raised
ValueErrorin the caller. - Create a
PaymentErrorcustom exception and raise it for insufficient balance. - Use
assertto check that a discount is not negative. - Explain the difference between
assertandraise. - Predict the output:
try:
print(10 / 2)
except ZeroDivisionError:
print("Error")
else:
print("No error")
finally:
print("Done")
- Find the mistake:
try:
amount = int("abc")
except:
pass
End of Level 8