• Oct 23, 2024

Python — try … finally versus with

  • DevTechie

In Python, both try . . . finally and with statement can be used ‌for resource management. Let’s explore the differences between them in this article.

In Python, both try . . . finally and with statement can be used ‌for resource management. Let’s explore the differences between them in this article.

Background

One typical programming difficulty is how to manage external resources like files, locks, and network connections. Sometimes a program will acquire those resources indefinitely, even if the program no longer requires them. This is known as a memory leak because it reduces available memory every time you create and open a new instance of a particular resource without first closing an existing one.

Managing resources effectively is often a difficult task. It involves both a setup and a teardown step (cleanup step). The later phase necessitates some cleanup operations, such as closing a file, releasing a lock, or terminating a network connection. If you forget to conduct these cleanup actions, your application will keep the resource alive even if not actively using it. This could jeopardize critical system resources such as memory and network bandwidth.

A common issue that can happen when developers interact with databases is when a program repeatedly creates new connections without retiring or reusing them. In those circumstances, the database backend may stop accepting new connections. To restore database functionality, an administrator may need to log in and manually kill stale connections.

Another frequent issue arises when developers work with files. Writing text to a file is typically a buffered operation. This signifies that when you call .write() on a file, it will first send text to a temporary buffer rather than the physical file itself. When the buffer is not full and developers forget to call .close(), some data may be lost forever.

One of the possible reasons for missing ‌cleanup actions, is exceptions. If your program encounters failures or exceptions, causing the control flow to skip the code responsible for releasing the resource in question. So, the program code must ensure cleanup actions in the event of exceptions also.

try...finally

The “try … finally” construct ensures that a specific block of code (the “finally” block) runs regardless of whether an exception occurs or not.

1 — It is a common resource management tool which ensures cleanup actions, such as closing files, releasing locks, closing database connections, web connections etc.

2 — The finally block always executes. This means that the finally block executes even if an exception is raised within the try block. Hence, try … finally can be used as resource management tool.

3 — Commonly employed when you need to release resources explicitly (e.g., closing files, database connections, etc. ).

with Statement

The with statement guarantees that a given piece of code is performed within a specified context such as an opened file or a network connection, and that the context is appropriately cleaned up when the with block of code is exited, even if an exception occurs.

The with statement is used to manage external resources efficiently. It simplifies resource management by automatically handling setup and teardown phases. The with statement is commonly used for file handling, database connections, and other context-based operations. It ensures that the necessary cleanup actions occur automatically, even if exceptions are raised within the block.

Following are the key-points about the with statement:

1 — Provides a cleaner and more concise way to manage resources.

2 — Automatically handles resource cleanup (e.g., closing files).

3 — Often used with context managers — objects that support the context management protocol i.e. objects which define __enter__() and __exit__()methods. Examples of such objects are file objects, database connections etc.

Syntax

try...finally

try:
    # Code that may raise an exception
    ...
finally:
    # Cleanup code (always executed)
    ...

with Statement

with open("file.txt", "r") as f:
    # Code that uses 'f' (automatically closes 'f' after use)
    ...
# Closes the file f when the execution control reaches this point

The next sections list the key differences between try … finally and the with statement.

Error Handling:

try...finally

1 — If an exception occurs within the try block, the finally block still executes.

2 — Potential bug: If opening the file fails, a second exception occurs in the finally clause because f is not bound i.e. there is no opened file to close.

with Statement

1 — Automatically handles exceptions and ensures proper cleanup.

2 — Safer and less error-prone than the try...finally approach.

Access to Exceptions

try … finally

No direct access to exceptions within the finally block.

with Statement

The with statement makes things less error-prone.

Readability

with Statement provides a more concise and readable way to manage resources than the try … finally construct. try … finallyCan lead to verbose and repetitive code.

Multiple Resources

try...finally

Requires nested try...finally blocks for managing multiple resources.

with Statement

Supports multiple resource usage in a single line.

Example

with open("input.txt", "r") as inp, open("output.txt", "w") as out:
    out.write(inp.read())

The example

Let’s understand the difference between try … finally andwith constructs with the help of an example.

Let the content of the file “my_fil.txt” be:

Data from file:
 Enjoy Python Programming with DevTechie!
This example is about file (resource) management using try ... finally and  with statement.

try … finally

Code:

def read_file_try_finally(filename):
        file = open (filename, "r")  # Open the file
        try:
            # Read data from the file
            data = file.read()
            # Process the data (e.g., print it)
            print (f"Data from file:\n {data}")
        finally:
            file.close()  # Close the file in the 'finally' block
    
# function definition ends here 
read_file_try_finally("my_file.txt") # call the function

Output:

Data from file:
 Enjoy Python Programming with DevTechie!
This example is about file (resource) management using try ... finally and  with statement.

with Statement

Code:

def read_file_with_statement(filename):
    
        with open (filename, "r") as file:
            # Read data from the file
            data = file.read()
            # Process the data (e.g., print it)
            print (f"Data from file:\n {data}")
# function definition ends here 
read_file_with_statement("my_file.txt") # call the function

Output:

Data from file:
 Enjoy Python Programming with DevTechie!
This example is about file (resource) management using try ... finally and  with statement.

You can observe that there is no need to close the file manually while using with statement.

The file is automatically closed when the with block exits (even if an exception occurs).

The problem with both of the above code is that for a non-existent file, they will throw an exception and print the traceback. You can use an extra try … except to rectify this issue. The updated codes are shown below.

The updated code will print a message is File ‘’ not found.

try … finally

def read_file_try_finally(filename):
    try:
        file = open (filename, "r")  # Open the file
        try:
            # Read data from the file
            data = file.read()
            # Process the data (e.g., print it)
            print ("Data from file:", data)
        finally:
            file.close()  # Close the file in the 'finally' block
    except FileNotFoundError:
        print (f"File '{filename}' not found.")
read_file_try_finally("sample.txt")

with Statement

def read_file_with_statement(filename):
    try:
        with open (filename, "r") as file:
            # Read data from the file
            data = file.read()
            # Process the data (e.g., print it)
            print ("Data from file:", data)
    except FileNotFoundError:
        print(f"File '{filename}' not found.")
read_file_with_statement("sample.txt")

Best Practices:

try...finally

1 — Use it when you need fine-grained control over resource management.

2 — Handle exceptions explicitly at an outer level.

with Statement

1 — Preferred for most cases.

2 — Encapsulates common resource management patterns.

3 — Makes code more readable and less prone to bugs.

Recapitulate

In summary, the with statement simplifies resource management, reduces boilerplate code, and ensures proper cleanup. It’s a powerful tool that Python developers should embrace!

Choose the approach that best suits your needs however remember that the with statement is more concise and less error prone.