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:
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.
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?
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.
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.
| Pattern | Where cleanup is described | Main idea |
|---|---|---|
| try...finally | In the finally block | The programmer explicitly places resource-release code in the cleanup block. |
| with | Through the __exit__ method | The 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
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
- A try...finally statement organizes cleanup after work in a try block.
- A common resource-management pattern acquires a resource in try and releases it in finally.
- The finally block keeps the release action connected to leaving the try-block work.
- A with statement can express this resource-management pattern more cleanly.
- 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.