We've explored how try and except blocks help us gracefully handle errors. But what if we want to execute some code only when no exceptions occur, or ensure a piece of code always runs, regardless of whether an error happened? This is where the else and finally clauses come into play in Python's error handling.
The else clause is attached to a try...except block. The code within the else block is executed only if the code within the try block completes successfully without raising any exceptions. Think of it as the 'happy path' – everything went as planned!
try:
# Code that might raise an exception
result = 10 / 2
except ZeroDivisionError:
print("You can't divide by zero!")
else:
# This code runs ONLY if no exception occurred in the try block
print(f"Division successful! Result: {result}")
finally:
print("This will always run.")In the example above, since 10 / 2 does not raise a ZeroDivisionError, the else block will execute, printing "Division successful! Result: 5.0". If the try block had been 10 / 0, the except block would have run, and the else block would have been skipped.
The finally clause is also attached to a try...except block. The code within the finally block is guaranteed to execute, no matter what. This means it will run if:
- The
tryblock completes successfully. - An exception occurs and is caught by an
exceptblock. - An exception occurs and is not caught by any
exceptblock (in this case, thefinallyblock runs before the exception propagates further).
The finally clause is incredibly useful for cleanup operations, such as closing files, releasing network connections, or freeing up resources. These actions need to happen regardless of whether your program encountered an error or not.
file = None
try:
file = open("my_data.txt", "r")
content = file.read()
# Process content here...
print("File read successfully.")
except FileNotFoundError:
print("Error: The file was not found.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
finally:
# This block will always execute to ensure the file is closed
if file:
file.close()
print("File has been closed.")
else:
print("No file was opened to close.")Notice how the finally block ensures file.close() is called, preventing resource leaks, even if FileNotFoundError or another exception occurs during file processing.
graph TD
A[Start]
B{Try block executes}
C{Exception occurs?}
D[Except block executes]
E[Else block executes]
F{Exception caught?}
G[Finally block executes]
H[End]
A --> B
B --> C
C -- Yes --> D
C -- No --> E
D --> F
E --> F
F -- Yes --> G
F -- No (Uncaught Exception) --> G
G --> H
You can use both else and finally in the same try statement. The else block runs if the try block succeeds, and the finally block runs after else (if it ran) or after an except block (if an exception occurred). The order of execution is: try -> except (if needed) -> else (if no exception) -> finally.
try:
number = int(input("Enter a number: "))
result = 100 / number
except ValueError:
print("Invalid input! Please enter an integer.")
except ZeroDivisionError:
print("Cannot divide by zero.")
else:
print(f"The result of 100 divided by {number} is: {result}")
finally:
print("Exiting the division operation.")By understanding and utilizing else and finally, you gain more sophisticated control over your program's execution flow, leading to more robust and predictable code.