Concepts / Finally Blocks

Finally Blocks

A finally block is code that must run no matter what—whether the try block succeeds, whether an exception is caught by an except block, or even if an exception is not caught at all.

  • Programming
Interactive lab

Try it: try / except / else / finally

How an exception jumps out of a try block to the first matching except clause, when else runs, and why finally always runs.

How it works

  1. Statements in try run until one raises an exception; the rest of try is skipped.
  2. Python checks the except clauses in order and runs the first one whose type matches.
  3. If nothing was raised, the else block runs instead.
  4. finally runs in every case.

Default run (9 steps): Call safe_divide('4'). … Return 25.0. Output was: Worked: 25.0 / Done.

Simplified: One fixed function; int() and / are modelled exactly (including how Python prints floats), but nothing is executed as Python.

Educational simulation

Loading the simulation…

Interactive lab

Try it: Context Managers and the with Statement

What with really does: it calls __enter__ before the block and __exit__ after it — even when an exception leaves the block — so a file opened with with is always closed before the exception continues; try/finally gives the same guarantee by hand, a bare close() is skipped by the exception, and a context manager whose __exit__ returns True suppresses the exception.

How it works

  1. with EXPR as f: evaluates EXPR (e.g. open(...)), calls its __enter__() and binds the returned value to f (a file's __enter__ returns the file itself).
  2. The block runs. If a statement raises (here int() on text that is not a number), the rest of the block is skipped.
  3. Whether the block finished or an exception is leaving it, Python calls __exit__(exc_type, exc, tb) — for a file this closes it. This happens before any outer except sees the exception.
  4. If __exit__ returns a true value the exception is suppressed and execution continues after the block; a file's __exit__ returns None, so the exception propagates to the nearest matching except (or stops the program).
  5. try: … finally: f.close() gives the same cleanup by hand (start with f = None and check it); open() … f.close() without either leaves the file open when an exception jumps past close().

Default run (10 steps): The program opens data.txt, which contains '4x\n'. Watch when the file is closed — and what happens if int() raises ValueError. … The program finished. The file was closed.

Simplified: Fixed program templates reading one line of data.txt (text you type, up to 12 ASCII characters) and converting it with int(). A small interpreter written for these statements runs them — nothing is executed — and it reproduces CPython 3.12's sys.settrace line/call/exception events, printed output, final error line and file state for every combination. File objects' own __enter__/__exit__ are C code, so they appear as protocol steps rather than traced lines.

Educational simulation

Loading the simulation…

The Resource Cleanup Problem

Imagine you open a file in your program to read data. Your code processes the file successfully, and you close it. But what if an exception is raised while you are reading? If you do not handle that exception carefully, your program might crash before reaching the line that closes the file. The file object remains open, consuming system resources. This is a resource leak. The finally block solves this problem by guaranteeing that certain cleanup code runs whether or not an exception was raised.

Key point

A finally block is code that must run no matter what—whether the try block succeeds, whether an exception is caught by an except block, or even if an exception is not caught at all.

How Finally Blocks Execute

The finally block is an optional part of a try-except statement. It comes after all except blocks (if any exist). The key guarantee is this: the finally block always executes, regardless of the path taken through the try-except structure. If the try block completes without raising an exception, the finally block runs. If an exception is raised and caught by an except block, the except block runs first, then the finally block runs. If an exception is raised and not caught, the finally block still runs before the exception propagates up to the caller.

Enter try blockExecute try codeException raised?No exceptionRun except blockRun finally blockContinue or propagateException caught byexcept?Exception not caughtNoYesYesNo
What code runs in what order when an exception occurs versus when it doesn't? Does the finally block always execute?

Structure and Syntax

A try-except-finally statement has a specific structure. The try block is required. At least one except block or a finally block (or both) must follow the try block. The finally block, if present, always comes last, after all except blocks. You cannot have a finally block without a try block.

tryrequiredcode blockrequiredexceptoptional (at least oneexcept or finally required)code blockoptionalfinallyoptional (must come last)code blockoptionalfollowed bythenfollowed bythenfollowed by
How do the try, except, and finally blocks relate to each other? Which ones are optional? What's the valid order?

File Resource Lifecycle with Finally

Consider what happens when you open a file. The file object is created and holds a connection to the file on disk. If you read from the file and an exception occurs, the file remains open unless you explicitly close it. The finally block is the ideal place to close the file because it guarantees the close operation runs regardless of whether an exception occurred.

Before try blockNo file openFile opened in tryFile object active,connection establishedException raisedduring readFile still open (resourceleak without finally)Finally blockexecutesFile.close() calledAfter finally blockFile closed, connectionreleasedopen()exception occursfinally runscleanup complete
What happens to the file object at each stage — when it opens, if an error occurs, and when finally closes it? What state is it in at each point?

Worked Example: Reading a File Safely

Worked example

Using Finally to Guarantee File Closure

Write code that opens a file, reads its contents, and ensures the file is closed even if an error occurs while reading.

  1. 1
    Open the file in the try block

    The try block is where you acquire the resource. You open the file here because you want to attempt the operation that might fail.

  2. 2
    Read and process the file contents

    Inside the try block, perform the operations that might raise an exception, such as reading lines or parsing data.

  3. 3
    Add an except block to handle specific errors

    If an exception occurs during reading, the except block catches it and handles it gracefully. For example, you might print an error message or use a default value.

  4. 4
    Add a finally block to close the file

    The finally block runs after the try and except blocks, regardless of whether an exception occurred. This is where you close the file, ensuring the resource is always released.

Result

The file is guaranteed to be closed whether the read succeeds or fails, preventing resource leaks.

python
Output (expected)
File not found
(or the file contents if successful)
File is closed in both cases

Why Finally Guarantees Cleanup

Without a finally block, you might write cleanup code at the end of your try-except block. However, if an exception is raised and not caught, the program jumps to the exception handler and skips any code after the exception point. The finally block solves this by being part of the exception handling mechanism itself. Python guarantees that the finally block runs before the exception propagates to the caller, ensuring cleanup happens even when an exception is not caught.

try blockopen file, read, close fileException during readJumps to except, skipsclose()try blockopen file, readException during readJumps to except, thenfinally runsexcept blockhandle errorexcept blockhandle errorfinally blockclose file (always runs)if exceptioncleanup skippedif exceptionthencleanup guaranteed
What's the difference between code that closes a file inside try versus inside finally? Why does finally guarantee cleanup?

Common Mistakes

  • Common mistake

    Putting resource cleanup code inside the try block after the main operation

    What it looks like
    try:
        file = open('data.txt')
        content = file.read()
        file.close()  # If read() raises an exception, this line is skipped
    Why it fails

    If an exception is raised during the main operation, the cleanup code is never reached. The file remains open.

    Do this instead

    Move the cleanup code to a finally block so it runs regardless of exceptions.

  • Common mistake

    Forgetting to handle the case where the resource was never successfully acquired

    What it looks like
    try:
        file = open('data.txt')
    except FileNotFoundError:
        pass
    finally:
        file.close()  # file may not exist if open() failed
    Why it fails

    If open() raises an exception, the file variable is never created. Calling file.close() in finally will raise a NameError.

    Do this instead

    Initialize the variable before the try block or check if it exists in finally: if 'file' in locals(): file.close()

  • Common mistake

    Assuming finally prevents the exception from propagating

    What it looks like
    try:
        raise ValueError('Something went wrong')
    finally:
        print('Cleanup done')
    # Program crashes here with ValueError
    Why it fails

    The finally block runs, but it does not catch or suppress the exception. After finally completes, the exception continues to propagate.

    Do this instead

    Use an except block to catch and handle the exception if you want to prevent it from propagating.

  • Common mistake

    Using finally for logic that should be in except

    What it looks like
    try:
        result = 10 / 0
    finally:
        print('Division failed')
    Why it fails

    The finally block runs regardless of whether an exception occurred. If you want to run code only when an exception occurs, use except.

    Do this instead

    Use except ZeroDivisionError: print('Division failed') to handle the specific error.

The Modern Alternative: Context Managers

While finally blocks are a fundamental tool for resource cleanup, Python provides a more elegant approach called context managers, implemented using the with statement. When you use with to open a file, Python automatically calls a cleanup method (called __exit__) when the block exits, whether or not an exception occurred. This eliminates the need to write explicit try-finally blocks for common resource management tasks.

python
Output (expected)
Both approaches ensure the file is closed. The with statement is cleaner and preferred for file operations.
Key point

The with statement (context manager) is the modern, preferred way to handle resource cleanup in Python. However, understanding finally blocks is essential because they are the underlying mechanism that makes context managers work, and they are still used in situations where a with statement is not available.

Practice: Applying Finally Blocks

MEDIUM

Write a try-except-finally block that attempts to read a configuration file. The try block should open and read the file. The except block should handle FileNotFoundError by printing a message. The finally block should close the file. What happens if the file does not exist? Does the finally block still run?

Hints
  • Remember that if open() fails, the file variable is not created. Consider initializing it before the try block.
  • The finally block always runs, even if the file was never successfully opened.
  • You can check if the file is open before closing it using hasattr(file, 'close').

Summary

Finally blocks are a critical tool for ensuring resource cleanup in Python. They guarantee that cleanup code runs regardless of whether an exception occurs, preventing resource leaks. A finally block always executes after the try and except blocks, even if an exception is raised and not caught. While finally blocks are essential for understanding exception handling, the modern with statement (context manager) is the preferred way to handle resource cleanup for most common scenarios. Understanding both approaches will make you a more effective Python programmer.

At a glance

  • A finally block is code that always runs after a try-except block, whether an exception occurs or not.
  • Finally blocks guarantee resource cleanup by running before exceptions propagate to the caller.
  • The finally block comes after all except blocks and is optional, but at least one except or finally block must follow the try block.
  • Common use cases include closing files, releasing database connections, and other resource management tasks.
  • Modern Python code often uses the with statement (context managers) instead of explicit try-finally blocks for cleaner, more readable code.

Related concepts

More concepts starting with F