Salvatore Lopiparo

Software Engineer

Python – try-finally and return statements

So I ran into an interesting issue today with try-finally and a return statement in Python.

I was creating a simple if-else on a library that was prone to erroring, so I needed to put it in a try-finally to make sure clean up always happened:

def get_error_prone_choice(value):
    try:
        if is_a_good_choice(value):
            return error_prone_function(True)
        else:
            return another_error_prone_function(False)
    finally:
        clean_up()

Here’s where the multiple exits from a function that Python allows adds some confusion. When does clean_up() happen? I needed to make sure that clean_up happened before it returned the value or bad things would happen (specifically a non-garbage collected object would start to accumulate from the inspect module).

It turns out the finally clause is called at the last possible moment when leaving the try-finally section even when leaving the function, which means I’m fine to use it as it is. However, returning from a finally AND from the main try statement can get confusing quickly:

def get_error_prone_choice(value):
    try:
        return error_prone_function(True)
    finally:
        return clean_up()

This will result in error_prone_function to be evaluated, then the result of clean_up() to be returned! The finally is always called at the last possible moment, meaning the return value is first set to the result from error_prone_function and then overwritten to the result from clean_up().