Skip to content

Exceptions & Error Handling

Errors are an inevitable part of programming. A network connection might drop, a user might enter a string where a number was expected, or a file might be missing. In Python, these events are handled through Exceptions.

Instead of your program crashing with a cryptic error message, exception handling allows you to intercept the error, respond gracefully, and keep the application running.


Before we can handle errors, we must distinguish between the two main types:

  1. Syntax Errors: These are “grammar” mistakes in your code (e.g., a missing colon or unmatched parentheses). Python catches these before the program even starts. You cannot “handle” these with try-except.
  2. Exceptions: These occur during execution (runtime). The code is grammatically correct, but something goes wrong during a specific operation (e.g., 1 / 0).

There are two primary ways to write “safe” code.

This style involves checking every possible failure point before performing an action.

if os.path.exists("data.txt"):
with open("data.txt") as f:
# process file
else:
# handle missing file

EAFP (Easier to Ask for Forgiveness than Permission)

Section titled “EAFP (Easier to Ask for Forgiveness than Permission)”

This is the idiomatic Python way. You assume things will work, but you are prepared to handle the failure.

try:
with open("data.txt") as f:
# process file
except FileNotFoundError:
# handle missing file

Why EAFP? It is often faster and more readable. More importantly, it avoids “Race Conditions” (where a file exists when you check it, but is deleted a millisecond later before you open it).


The try block contains the “dangerous” code, while the except block contains the “safety net.”

safe_division.py
try:
num = int(input("Enter a number: "))
result = 100 / num
print(f"Result: {result}")
except ValueError:
print("Error: That wasn't a valid integer.")
except ZeroDivisionError:
print("Error: You cannot divide by zero.")
except Exception as e:
print(f"An unexpected error occurred: {e}")

By using except Exception as e, you capture the exception object. This object contains valuable information, such as the error message, which you can log or display.


A complete exception handler can have four parts.

ClausePurpose
tryThe code that might fail.
exceptRuns only if an error occurs.
elseRuns only if no error occurs in the try block.
finallyRuns no matter what (even if the program crashes or returns).
resource_management.py
try:
f = open("log.txt", "w")
f.write("System update...")
except IOError:
print("Could not write to file.")
else:
print("Write successful!")
finally:
f.close()
print("File resource closed.")

Context: The finally block is essential for “Cleanup” tasks like closing database connections or network sockets, ensuring you don’t leak resources.


You can trigger your own exceptions using the raise keyword. This is useful for enforcing business logic.

custom_raise.py
def set_age(age):
if age < 0:
raise ValueError("Age cannot be negative!")
return age
try:
set_age(-5)
except ValueError as e:
print(e) # Output: Age cannot be negative!

When an exception is raised, Python’s execution doesn’t just stop. It begins a process called Stack Unwinding:

  1. Python looks for a try-except block in the current function.
  2. If none is found, it “pops” the current function off the call stack and goes back to the caller.
  3. It repeats this process, climbing up the stack until it finds a handler.
  4. If it reaches the very top (the global scope) without finding a handler, the program terminates and prints the Traceback.

  • Be Specific: Never use a bare except:. It will catch things you don’t want to catch, like SystemExit (when you try to quit the program).
  • Keep Try Blocks Small: Only put the lines of code that might actually raise the exception inside the try block. This prevents you from accidentally catching errors you didn’t intend to.
  • Don’t Silence Errors: Avoid except: pass unless you have a very specific reason. If you ignore an error, you make debugging nearly impossible later.