3.1 Catching Exceptions
We wouldn't be talking so much about exceptions if we just had to watch them. Exceptions are special objects your Python program can work with. Exception handling is a critical part of programming that helps improve the reliability and resilience of programs.
In Python, structures like try
, except
, else
, and finally
are used to catch and handle exceptions. These structures allow you to intercept errors that occur during program execution and take appropriate actions.
The try-except
Construct
The try-except
construct is used for catching and handling exceptions. The try
block contains code that might throw an exception, while the except
block contains code that will run if an exception occurs.
Example:
try:
result = 10 / 0
except ZeroDivisionError:
print("Error: division by zero.")
If a ZeroDivisionError
exception occurs in the code within the try
block, it will be caught by the except
block, and the print()
function will be called.
Handling Multiple Exceptions
You can handle multiple types of exceptions by specifying them in separate except
blocks.
try:
result = int("abc")
except ZeroDivisionError:
print("Error: division by zero.")
except ValueError:
print("Error: invalid value.")
Catching All Exceptions
If you want to catch all exceptions, you can use an except
block without specifying a specific exception type. However, this is not recommended as it can make debugging difficult and hide important errors.
try:
result = 10 / 0
except:
print("An error occurred.")
3.2 The else
and finally
Statements
Besides try
and except
, there are two more optional statements: else
and finally
. Let's talk about them a bit more.
The try-except-else
Construct
The else
block is used to execute code if no exceptions occur in the try
block.
try:
result = 10 / 2
except ZeroDivisionError:
print("Error: division by zero.")
else:
print(f"Result: {result}")
The try-except-finally
Construct
The finally
block contains code that will run no matter whether an exception occurred or not. It's useful for releasing resources or doing cleanup tasks.
try:
result = 10 / 0
except ZeroDivisionError:
print("Error: division by zero.")
finally:
print("This block always executes.")
Complete Example: try-except-else-finally
Example:
try:
result = 10 / 2
except ZeroDivisionError:
print("Error: division by zero.")
else:
print(f"Result: {result}")
finally:
print("This block always executes.")
3.3 Example of try-except-else-finally
Let's break down a big real-life example. For instance, we're trying to read data from a file on disk — how hard can that be?
file = open("file.txt", "r")
content = file.read()
print(content)
What could go wrong? Pretty much everything:
- The file might be missing. Maybe it was accidentally deleted, never written, or your program is running on another computer where it never existed.
- File read error. Your program doesn’t have access to it because it’s in a directory that requires admin rights.
- Another program is currently writing to the file and reading from it isn’t allowed — it's got exclusive access.
Is that not enough? Don't forget that no matter where the error happens in your file operations, you must always "close" it so the operating system releases the resources allocated for it.
So the real code might look something like this:
try:
file = open("non_existent_file.txt", "r")
content = file.read()
except FileNotFoundError:
print("Error: file not found.")
except IOError:
print("Error: I/O error.")
else:
print(content)
finally:
if 'file' in locals() and not file.closed:
file.close()
print("File closed.")
Welcome to the real world where you need to write code not only for the "working scenario," but also for all possible things that might go wrong.
Alright, I won't scare you — it's easier than it seems. You just need to understand what corner cases are and add checks for standard errors as you go. The rest will be handled by modern frameworks.
GO TO FULL VERSION