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