Exception Handling
Python provides the try ... except construct to handle exceptions that may occur in a block of code. The basic idea is: you “try” to execute some code, and if a specific exception happens, you “catch” it in an except block and handle it gracefully instead of crashing. Optional else and finally clauses provide additional control flow for when no exceptions occur, or for cleanup actions that should run regardless of an exception.
Syntax of try/except:
try:
# Code that might raise an exception
except SomeException:
# Handle the exception of type SomeException
You can also have multiple except blocks to handle different exception types, and a generic catch-all. Here’s a more complete pattern including else and finally:
try:
# 1. Code that could raise an exception
except ValueError:
# 2. This block runs if a ValueError was raised in try
except Exception as e:
# 3. This runs for any other exception not caught above
# (using Exception catches most errors)
else:
# 4. This runs if no exception occurred at all in try
finally:
# 5. This runs at the end, whether or not an exception happened
Let’s break down the behavior:
-
try block: Python executes the code inside
tryfirst. If no error occurs, it skips allexceptblocks. -
except blocks: If an exception is raised inside the
tryblock, Python looks for anexceptblock with a matching exception type. If it finds a match, it executes that block and then continues after thetry/exceptstructure. If no matchingexceptis found, the exception propagates upward (and if uncaught, you’ll get a traceback). You can have multipleexceptclauses to handle different exceptions separately. For example, oneexceptforValueErrorand another forZeroDivisionError, etc. Only the first matchingexceptwill run. -
else block: This is optional. The
elseclause runs only if thetryblock did not raise any exception. This is useful for code that should execute when thetrysucceeds, and you want to keep that code outside of thetryto avoid accidentally catching exceptions it might raise. For instance, you might open a file in thetry, handle anIOErrorinexcept, and put code that processes the file in theelseso it only runs if the file was opened successfully. -
Finally block: This clause runs no matter what. Whether the
tryblock finishes normally, or an exception was raised (even if it was caught, or even if it wasn’t caught), the code infinallywill execute after. This is typically used for cleanup actions – for example, closing a file or releasing a resource, to ensure it always happens. Even if youreturnorbreakinsidetryorexcept, thefinallywill still execute just before that action completes.
Example with else and finally:
def divide(a, b):
try:
result = a / b
except ZeroDivisionError:
print("Cannot divide by zero!") # Handle division by zero
result = None
else:
print("Division successful! result =", result) # Runs only if no exception
finally:
print("Execution of divide() is done.") # Runs regardless of what happened
return result
divide(10, 2)
print("---")
divide(5, 0)
Running this example would produce output like:
Division successful! result = 5.0
Execution of divide() is done.
---
Cannot divide by zero!
Execution of divide() is done.
Notice how:
-
When
bwas 2 (no exception), theexceptwas skipped, theelseran confirming success, andfinallyran last. -
When
bwas 0 (causing aZeroDivisionError), theexcept ZeroDivisionErrorran, theelsewas skipped (since an exception occurred), and thenfinallyran. In both cases,finallyexecuted at the end.
Why use an else?
It helps keep the successful path separate from the error handling. If you put everything in the try, you might catch an exception from code that you didn’t intend to. The Python docs recommend using else for code that should run only when no exceptions happened. In our example, printing the success message in else ensures it doesn’t run when an exception occurs.
Important: The finally is executed regardless of whether an exception was handled or not. Even if you don’t catch an exception (or if you use sys.exit() or a return inside try), the finally block will still execute before the program fully unwinds. This guarantee is why finally is used for cleanup (closing files, releasing locks, etc.) so resources are not left hanging.
