1. Introduction
The finally clause attaches cleanup code to a try statement that is guaranteed to execute regardless of whether an exception occurred, whether it was caught, or even whether the try block exits early via return, break, or continue. It is the standard place to release resources such as closing files, releasing locks, or closing network connections.
Cricket analogy: Regardless of whether a match ends in a win, loss, or is abandoned for rain, the groundskeeper always rolls out the covers to protect the pitch afterward — cleanup that happens no matter how the match concluded.
finally runs after the try block and any matching except block have finished, and it runs even if no except clause is present at all.
Cricket analogy: The covers go on after the umpires call stumps, whether it was a normal close of play or an early finish due to bad light, and they still go on even if there was no rain delay at all during the day.
2. Syntax
try:
risky_operation()
except SomeError as e:
handle(e)
finally:
cleanup() # always runs, exception or not3. Explanation
finally runs in every case: when the try block completes normally, when an exception is raised and caught by an except clause, when an exception is raised and not caught at all (finally still runs before the exception propagates further), and even when the try block hits a return, break, or continue statement.
Cricket analogy: The pitch gets covered whether the match finishes its full course, a batsman is controversially given out and the umpire's decision holds, the decision is overturned entirely, or the umpires abandon play early due to bad light — covers go on every single time.
finally always runs even after a return statement inside try. If try has return 1 and finally has return 2, the finally's return value overrides the try's return value — this is a well-known gotcha. In general, avoid returning from within a finally block, since it silently discards whatever the try/except was about to return or any exception that was about to propagate.
Because of this guarantee, finally is ideal for cleanup that must happen unconditionally, such as file.close() or lock.release(), though the with statement (context managers) is usually preferred for resource cleanup because it expresses the same guarantee more concisely.
Cricket analogy: Rolling the covers onto the pitch after every session is non-negotiable groundskeeping, similar to file.close(), though many modern grounds now use automated covering systems that guarantee the same protection more reliably than manual crews.
4. Example
def demo_normal():
try:
print("try: running normally")
finally:
print("finally: cleanup after normal run")
def demo_exception():
try:
raise ValueError("boom")
except ValueError as e:
print(f"except: caught {e}")
finally:
print("finally: cleanup after exception")
def demo_return_override():
try:
return 1
finally:
print("finally: runs even after return")
return 2
demo_normal()
demo_exception()
print("return value:", demo_return_override())5. Output
try: running normally
finally: cleanup after normal run
except: caught boom
finally: cleanup after exception
finally: runs even after return
return value: 26. Key Takeaways
- finally always executes, whether or not an exception was raised.
- finally runs even if the exception is uncaught, right before it propagates.
- finally runs even when try exits via return, break, or continue.
- A return statement inside finally overrides any return from try or except.
- finally is the standard place for guaranteed cleanup like closing files or releasing locks.
- The
withstatement is often a cleaner alternative for resource cleanup.
Practice what you learned
1. If try contains `return 1` and finally contains `return 2`, what does the function return?
2. Does finally run if the exception raised in try is not caught by any except clause?
3. What is a common best-practice alternative to a bare finally block for resource cleanup?
4. In the lesson's demo_return_override(), why does 'finally: runs even after return' print before the function actually returns?
5. Does finally run for a try block that contains a `break` inside a loop?
Was this page helpful?
You May Also Like
try-except in Python
How to use try-except blocks to catch and handle exceptions gracefully, including catching multiple exception types.
else Clause in Exception Handling
How the try/except/else clause runs code only when no exception occurred, and how it differs from finally.
Exceptions in Python
What exceptions are, how Python's built-in exception hierarchy is structured, and how errors propagate through a program.
with Statement (Context Managers) in Python
Learn how the 'with' statement uses the context manager protocol (__enter__/__exit__) to guarantee cleanup, such as automatically closing files.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics