Concepts / try...finally statements

try...finally statements

Acquiring a resource in the try block and subsequently releasing the resource in the finally block is a common pattern. Hence, there is also a with statement that enables this to be done in a clean manner:

  • Programming

Why Cleanup Needs a Plan

Some operations temporarily acquire a resource. A program may need to release that resource afterward, including when the main operation does not complete as expected. A try...finally statement provides a structure for placing the release action in a finally block after the resource is acquired in the try block.

The central pattern is acquire in try, perform the required work, and release in finally.

Tracing the Control Flow

Control first enters the try block. When the try block finishes, execution reaches the finally block. The finally block is the place for the action that must be carried out as the try-block work is being left, such as releasing a resource. This makes the cleanup part of the control-flow structure rather than an action that depends on remembering a separate call later.

finishesraisesenterenterafter cleanupafter cleanuptry blockmain worknormal completionfinally blockcleanupexecution continuesexceptionexception propagates
What happens when the try block completes normally or raises an exception, and how does execution reach the finally block?

What do you think happens?

A resource is acquired in the try block, and the work in that block raises an exception. Which part is responsible for the release action?

  • Only code after the complete try statement
  • The finally block
  • The try block before the resource is acquired
Reveal answer

Answer: The finally block

The common pattern places resource acquisition in the try block and resource release in the finally block, so the release action is associated with leaving the try-block work.

The Resource Lifecycle

A resource-management pattern has two connected stages. First, the program acquires the resource inside the try block. Next, after the try-block work is left, the program releases the resource inside the finally block. The value of this arrangement is that acquisition and release remain visibly connected in one statement structure.

try acquiresusefinally releasesresourcenot acquiredresourceacquiredtry workuse resourceresourcereleased
How does a resource move from acquisition in the try block to release in the finally block, even when the main work does not complete normally?

A Resource That Must Be Released

A program needs to acquire a resource, use it during its main operation, and release it after the try-block work.

Acquire: Place the resource-acquisition action in the try block.

Use: Perform the operation that needs the resource in the try block.

Release: Place the resource-release action in the finally block so it belongs to the cleanup stage.

The structure clearly separates the main operation from the release action while keeping both actions in one control-flow pattern.

Choosing with Instead

The try...finally pattern is useful, but the same kind of resource lifecycle can be expressed with a with statement. The source describes with as a way to perform this pattern in a clean manner. Its __exit__ method takes care of the code that would otherwise have been written in a finally block.

explicit lifecyclehandled automaticallyacquiretry blockacquirewith statementreleasefinally block__exit__automatic cleanup
What is the difference between explicitly placing release logic in finally and allowing with to manage the lifecycle?
PatternWhere cleanup is describedMain idea
try...finallyIn the finally blockThe programmer explicitly places resource-release code in the cleanup block.
withThrough the __exit__ methodThe cleanup corresponding to the finally-block code is handled automatically.

Use the try...finally pattern to understand the lifecycle explicitly. When a suitable with-based resource interface is available, with can provide the cleaner form described by the source.

Mistakes Beginners Make

  • Putting resource acquisition only in the finally block.

    The pattern described by the source acquires the resource in the try block and releases it in the finally block.

    Fix: Keep acquisition in try and release in finally.

  • Treating finally as a replacement for all exception handling.

    The source distinguishes try...except from try...finally and discusses them as separate statement uses.

    Fix: Use finally for the cleanup stage and learn try...except separately for exception-handling behavior.

  • Repeating explicit try...finally code when a with statement can manage the resource lifecycle.

    The source states that with helps avoid repeatedly using explicit try...finally statements because its __exit__ method handles the corresponding cleanup code.

    Fix: Consider whether the resource supports the with-based pattern described in the source.

Practice the Trace

EASY

A program acquires a resource in a try block. The main operation then raises an exception. Describe the order of the two important stages: the main operation and the release action. Then explain why placing the release action in finally is useful.

Hints
  • Identify where acquisition occurs.
  • Identify where release occurs.
  • Think about which block owns the cleanup action.

Practice Answer

Trace a resource lifecycle when the try-block operation does not complete normally.

First: The resource is acquired in the try block.

Next: The main operation runs in the try block and does not complete normally.

Then: Control reaches the finally block, where the resource-release action is placed.

The resource lifecycle remains organized because the acquisition and release actions are assigned to their respective blocks.

Key Takeaways

  1. A try...finally statement organizes cleanup after work in a try block.
  2. A common resource-management pattern acquires a resource in try and releases it in finally.
  3. The finally block keeps the release action connected to leaving the try-block work.
  4. A with statement can express this resource-management pattern more cleanly.
  5. The __exit__ method handles the code that would otherwise be written in a finally block.

Key Takeaways

  • try...finally separates the main operation from its cleanup action.
  • The common resource pattern is acquisition in try followed by release in finally.
  • The cleanup action belongs in finally rather than being left to a later, separately remembered step.
  • The with statement and its __exit__ method can manage this lifecycle automatically and cleanly.