py4u blog

Python: Does the finally Clause Run When Using continue in a Try-Finally Loop? Behavior Explained

In Python, the try-finally statement is a powerful tool for ensuring cleanup code runs regardless of how a block of code exits—whether normally, via an exception, or even through control flow statements like return or break. But what happens when you use continue inside a loop with try-finally? Does the finally clause still execute, or does continue skip it entirely?

This question is surprisingly common among Python developers, especially those working with loops that require reliable resource management (e.g., closing files, releasing network connections). In this blog, we’ll demystify the behavior of finally when paired with continue, explore why it works the way it does, and share practical best practices to avoid pitfalls.

2026-01

Table of Contents#

  1. Understanding Try-Finally in Python
  2. The Role of continue in Loops
  3. Does finally Run with continue? Let’s Test!
  4. Why Does This Happen? Under the Hood
  5. Practical Implications and Best Practices
  6. Common Pitfalls to Avoid
  7. Conclusion
  8. References

Understanding Try-Finally in Python#

Before diving into continue, let’s recap how try-finally works. The try block contains code that may execute normally or raise an exception. The finally block, which follows try (and optionally except), contains code that always runs when the try block exits—no matter how the exit occurs.

Basic Syntax:#

try:
    # Code that might raise an exception or exit early
    risky_operation()
finally:
    # Cleanup code that MUST run
    cleanup_resources()

Key Takeaway: finally is designed for "guaranteed cleanup." Whether the try block finishes normally, raises an uncaught exception, or exits via return/break, finally executes.

The Role of continue in Loops#

The continue statement is used inside loops to skip the remaining code in the current iteration and immediately jump to the next iteration.

Example of continue:#

for i in range(3):
    if i == 1:
        continue  # Skip iteration 1
    print(f"Processed {i}")

Output:

Processed 0
Processed 2

Here, when i=1, continue skips print(f"Processed {i}") and moves to the next iteration (i=2).

Does finally Run with continue? Let’s Test!#

The critical question: When continue is encountered inside a try block, does the finally clause execute before jumping to the next iteration? Let’s test with concrete examples.

Test Case 1: continue in try Block (No Exceptions)#

We’ll loop 3 times, use continue to skip code in the first two iterations, and check if finally runs each time.

for i in range(3):
    try:
        print(f"Starting iteration {i}")
        if i < 2:
            continue  # Skip remaining code in try block for i=0,1
        print(f"Completed iteration {i} (no continue)")  # Runs only for i=2
    finally:
        print(f"Finally clause executed for iteration {i}\n")

Output:

Starting iteration 0
Finally clause executed for iteration 0

Starting iteration 1
Finally clause executed for iteration 1

Starting iteration 2
Completed iteration 2 (no continue)
Finally clause executed for iteration 2

Observation: For i=0 and i=1, continue skips the print("Completed...") line, but finally still runs. For i=2, continue isn’t triggered, so the try block completes normally—and finally still runs.

Test Case 2: continue After an Exception in try#

What if the try block raises an exception before continue? Does finally still execute?

for i in range(2):
    try:
        print(f"Starting iteration {i}")
        if i == 0:
            raise ValueError("Oops! An error occurred.")  # Exception before continue
        continue  # This runs only for i=1 (no exception)
    except ValueError as e:
        print(f"Caught exception: {e}")
    finally:
        print(f"Finally clause executed for iteration {i}\n")

Output:

Starting iteration 0
Caught exception: Oops! An error occurred.
Finally clause executed for iteration 0

Starting iteration 1
Finally clause executed for iteration 1

Observation: Even when the try block exits early due to an exception (for i=0), finally runs. For i=1, continue skips the rest of the try block, but finally still executes.

Test Case 3: break vs. continue (for Comparison)#

To highlight continue’s uniqueness, let’s compare with break (which exits the loop entirely).

print("=== Using break ===")
for i in range(2):
    try:
        print(f"Starting iteration {i}")
        if i == 0:
            break  # Exit loop entirely
    finally:
        print(f"Finally (break) executed for iteration {i}\n")
 
print("\n=== Using continue ===")
for i in range(2):
    try:
        print(f"Starting iteration {i}")
        if i == 0:
            continue  # Skip to next iteration
    finally:
        print(f"Finally (continue) executed for iteration {i}\n")

Output:

=== Using break ===
Starting iteration 0
Finally (break) executed for iteration 0

=== Using continue ===
Starting iteration 0
Finally (continue) executed for iteration 0

Starting iteration 1
Finally (continue) executed for iteration 1

Observation: With break, the loop exits after the first iteration, but finally still runs once. With continue, the loop proceeds to the next iteration, and finally runs for every iteration.

Verdict:#

Yes! The finally clause always runs when continue is encountered in a try block. It executes immediately after the try block exits (due to continue) and before jumping to the next iteration.

Why Does This Happen? Under the Hood#

Python’s design guarantees that finally executes whenever the try block is exited, regardless of the exit mechanism. The Python Language Reference explicitly states:

"A finally clause is always executed before leaving the try statement, whether normally or via an exception, return, break, or continue."

When continue is encountered:

  1. The try block exits early (skipping remaining code in the iteration).
  2. The finally clause runs immediately.
  3. Control jumps to the next iteration of the loop.

This behavior is intentional: finally is meant to enforce cleanup, even when loops skip iterations.

Practical Implications and Best Practices#

Understanding that finally runs with continue is critical for writing robust code, especially for resource management. Here’s how to apply this knowledge:

1. Safely Clean Up Resources#

Use finally to release resources (e.g., file handles, network connections) when continue skips iterations.

Example: Closing a File with continue

with open("data.txt", "r") as f:  # `with` is better, but `finally` works here too
    for line in f:
        try:
            if line.startswith("#"):
                continue  # Skip comments
            process_line(line)
        finally:
            # Optional: Additional cleanup (e.g., reset state)
            reset_parser()

Even when continue skips comment lines, reset_parser() runs, ensuring the parser is ready for the next line.

2. Avoid Side Effects in finally#

Be cautious modifying loop variables or state in finally, as changes affect the next iteration.

Example: Modifying a Loop Variable in finally

count = 0
while count < 3:
    try:
        print(f"count = {count}")
        if count == 1:
            continue
        count += 1
    finally:
        count += 1  # This runs EVERY time, even after continue!
 
# Output:
# count = 0
# count = 2
# count = 3 (loop exits)

Here, finally increments count even when continue is triggered, causing unexpected loop behavior.

Common Pitfalls to Avoid#

  • Assuming finally Doesn’t Run with continue: Never skip critical cleanup (e.g., closing a database connection) because you think continue bypasses finally. It doesn’t.
  • Overusing finally: Use finally only for cleanup. Avoid complex logic here, as it can make code hard to debug.
  • Ignoring finally’s Timing: finally runs after the try block exits but before continue jumps to the next iteration. This timing can affect state changes.

Conclusion#

To answer the question: Yes, the finally clause always runs when continue is used in a try block. Python guarantees finally execution for all try block exits, including continue, break, exceptions, and normal completion.

This behavior makes finally indispensable for resource cleanup, ensuring files, connections, and other resources are properly released—even when loops skip iterations. By mastering try-finally with continue, you’ll write more reliable, robust Python code.

References#