Introduction
In this lab, you will learn how to check if an exception was caught in Python using different techniques. The lab focuses on exception handling, a crucial aspect of writing robust and reliable Python code.
The lab guides you through understanding the exception handling flow using try...except blocks to gracefully handle errors like ZeroDivisionError. You'll learn how to set a flag within the except block to indicate that an exception has been caught. Finally, the lab will introduce the concept of using context managers for more controlled exception handling.
Learn Exception Handling Flow
In this step, you will learn about exception handling in Python. Exception handling is a crucial part of writing robust and reliable code. It allows you to gracefully handle errors that might occur during the execution of your program, preventing it from crashing and providing a more user-friendly experience.
Let's start with a simple example. Imagine you want to divide two numbers, but the second number might be zero. Dividing by zero is an undefined operation and will raise a ZeroDivisionError in Python.
Open the VS Code editor in the LabEx environment.
Create a new file named
division.pyin the~/projectdirectory.touch ~/project/division.pyEdit the
division.pyfile and add the following code:## division.py numerator = 10 denominator = 0 result = numerator / denominator print(result)Run the script using the
pythoncommand:python ~/project/division.py
You will see an error message similar to this:
Traceback (most recent call last):
File "/home/labex/project/division.py", line 4, in <module>
result = numerator / denominator
ZeroDivisionError: division by zero
This error message indicates that a ZeroDivisionError occurred because we tried to divide by zero. Without exception handling, the program terminates abruptly.
Now, let's use exception handling to handle this error gracefully.
Modify the
division.pyfile to include atry...exceptblock:## division.py numerator = 10 denominator = 0 try: result = numerator / denominator print(result) except ZeroDivisionError: print("Error: Cannot divide by zero.")In this code, the
tryblock contains the code that might raise an exception. If aZeroDivisionErroroccurs within thetryblock, the code in theexceptblock will be executed.Run the script again:
python ~/project/division.py
Now, instead of crashing, the program will output:
Error: Cannot divide by zero.
This demonstrates the basic structure of exception handling:
- The
tryblock encloses the code that might raise an exception. - The
exceptblock specifies the type of exception to catch and the code to execute if that exception occurs.
You can also catch multiple types of exceptions using multiple except blocks:
## division.py
numerator = 10
denominator = "abc"
try:
result = numerator / int(denominator)
print(result)
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
except ValueError:
print("Error: Invalid input. Please enter a number.")
In this example, we've added a ValueError exception handler. If the denominator cannot be converted to an integer (e.g., if it's a string like "abc"), a ValueError will be raised, and the corresponding except block will be executed.
Run the script:
python ~/project/division.py
Output:
Error: Invalid input. Please enter a number.
Exception handling allows you to write more robust and user-friendly programs by anticipating and handling potential errors.
Set a Flag in except Block
In this step, you will learn how to use a flag within an except block to control the flow of your program based on whether an exception occurred or not. This is a useful technique when you need to perform different actions depending on the outcome of the try block.
Building upon the previous example, let's say you want to calculate the reciprocal of a number, but only if the division was successful. You can use a flag to indicate whether the division was successful and then calculate the reciprocal accordingly.
Open the VS Code editor in the LabEx environment.
Modify the
division.pyfile in the~/projectdirectory to include a flag:## division.py numerator = 10 denominator = 2 success = True ## Initialize the flag to True try: result = numerator / denominator print("Result of division:", result) except ZeroDivisionError: print("Error: Cannot divide by zero.") success = False ## Set the flag to False if an error occurs except ValueError: print("Error: Invalid input. Please enter a number.") success = False ## Set the flag to False if an error occurs else: print("No exception occurred.") if success: try: reciprocal = 1 / result print("Reciprocal:", reciprocal) except ZeroDivisionError: print("Cannot calculate reciprocal of zero.") else: print("Reciprocal calculation skipped due to error.")In this code:
- We initialize a flag named
successtoTruebefore thetryblock. - If a
ZeroDivisionErrororValueErroroccurs, we set thesuccessflag toFalsewithin the correspondingexceptblock. - After the
try...exceptblock, we check the value of thesuccessflag. If it's stillTrue, it means no exception occurred, and we can safely calculate the reciprocal. Otherwise, we skip the reciprocal calculation. - We also added an
elseblock, which will be executed if no exception occurs in thetryblock.
- We initialize a flag named
Run the script with a valid denominator:
python ~/project/division.pyOutput:
Result of division: 5.0 No exception occurred. Reciprocal: 0.2Now, change the
denominatorto0and run the script again:## division.py numerator = 10 denominator = 0 ## Change the denominator to 0 success = True try: result = numerator / denominator print("Result of division:", result) except ZeroDivisionError: print("Error: Cannot divide by zero.") success = False except ValueError: print("Error: Invalid input. Please enter a number.") success = False else: print("No exception occurred.") if success: try: reciprocal = 1 / result print("Reciprocal:", reciprocal) except ZeroDivisionError: print("Cannot calculate reciprocal of zero.") else: print("Reciprocal calculation skipped due to error.")Run the script:
python ~/project/division.pyOutput:
Error: Cannot divide by zero. Reciprocal calculation skipped due to error.
This demonstrates how you can use a flag in the except block to control the flow of your program and perform different actions based on whether an exception occurred or not.
Use Context Managers for Control
In this step, you will learn how to use context managers in Python to simplify exception handling and ensure that resources are properly managed, even if exceptions occur. Context managers are particularly useful when working with files, network connections, and other resources that need to be explicitly closed or released.
A context manager is an object that defines the __enter__ and __exit__ methods. The with statement is used to execute a block of code within the context of a context manager. The __enter__ method is called when the with block is entered, and the __exit__ method is called when the with block is exited, regardless of whether an exception occurred.
Let's start with a simple example of reading a file using a context manager.
Open the VS Code editor in the LabEx environment.
Create a new file named
file_handling.pyin the~/projectdirectory.touch ~/project/file_handling.pyEdit the
file_handling.pyfile and add the following code:## file_handling.py filename = "my_file.txt" try: with open(filename, "w") as f: f.write("Hello, LabEx!\n") f.write("This is a test file.\n") except IOError as e: print(f"An I/O error occurred: {e}") try: with open(filename, "r") as f: content = f.read() print("File content:") print(content) except FileNotFoundError: print(f"The file '{filename}' was not found.") except IOError as e: print(f"An I/O error occurred: {e}")In this code:
- We use the
with open(filename, "w") as f:statement to open the filemy_file.txtin write mode ("w"). Theopen()function returns a file object, which is assigned to the variablef. - The
withstatement ensures that the file is automatically closed when the block is exited, even if an exception occurs. - We write two lines of text to the file using the
f.write()method. - We then use the
with open(filename, "r") as f:statement to open the same file in read mode ("r"). - We read the entire content of the file using the
f.read()method and print it to the console. - We wrap the file operations in
try...exceptblocks to handle potentialFileNotFoundErrorandIOErrorexceptions.
- We use the
Run the script:
python ~/project/file_handling.pyOutput:
File content: Hello, LabEx! This is a test file.If the file
my_file.txtdoes not exist, the script will create it and write the specified content. If the file already exists, its content will be overwritten. Thewithstatement ensures that the file is properly closed in either case.
Let's consider another example where an exception might occur during file processing:
## file_handling.py
filename = "my_file.txt"
try:
with open(filename, "r") as f:
for line in f:
## Simulate an error during processing
if "test" in line:
raise ValueError("Simulated error during processing")
print("Line:", line.strip())
except FileNotFoundError:
print(f"The file '{filename}' was not found.")
except ValueError as e:
print(f"A value error occurred: {e}")
except IOError as e:
print(f"An I/O error occurred: {e}")
In this example, we simulate an error by raising a ValueError if the line contains the word "test". Even if this error occurs, the with statement ensures that the file is properly closed.
Run the script:
python ~/project/file_handling.py
Output:
Line: Hello, LabEx!
A value error occurred: Simulated error during processing
Context managers provide a clean and reliable way to manage resources and handle exceptions in Python. They ensure that resources are properly released, even if errors occur, making your code more robust and easier to maintain.
Summary
In this lab, you begin by learning about exception handling in Python, a crucial technique for writing robust code. You start with a simple division example that raises a ZeroDivisionError when dividing by zero, causing the program to terminate. You then implement a try...except block to gracefully handle the ZeroDivisionError, preventing the program from crashing and printing an informative error message instead.



