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