finallyIntermediate Examples

Block that always executes after try/except, used for cleanup

finally with return

How finally interacts with return statements.

python
def test_finally():
    try:
        print("  In try")
        return "from try"
    except:
        print("  In except")
        return "from except"
    finally:
        print("  In finally (runs before return!)")

result = test_finally()
print(f"Got: {result}")

print()

# finally can override the return value (but don't do this!)
def bad_practice():
    try:
        return 1
    finally:
        return 2  # overrides the return from try!

print(f"bad_practice() = {bad_practice()}")
Expected Output
  In try
  In finally (runs before return!)
Got: from try

bad_practice() = 2

finally runs even when the try block returns. If finally also has a return, it overrides the try's return — avoid this anti-pattern.

finally for resource cleanup

Ensuring resources are released.

python
# Manual resource management with finally
resources = []

def acquire(name):
    resources.append(name)
    print(f"  Acquired: {name}")
    return name

def release(name):
    resources.remove(name)
    print(f"  Released: {name}")

# Works even if processing fails
try:
    r = acquire("database")
    print("  Processing...")
    raise RuntimeError("Something went wrong")
except RuntimeError as e:
    print(f"  Error: {e}")
finally:
    if "database" in resources:
        release("database")

print(f"Resources still held: {resources}")
Expected Output
  Acquired: database
  Processing...
  Error: Something went wrong
  Released: database
Resources still held: []

finally is the manual version of what 'with' statements automate. Use 'with' when possible, but finally is still useful for custom cleanup logic.

Want to try these examples interactively?

Open Intermediate Playground