Why do we need "try-finally" when using @contextmanager decorator?

Question:

I wonder why we need to use a try-finally when using a the @contextmanager decorator.

The provided example suggests:

from contextlib import contextmanager

@contextmanager
def managed_resource(*args, **kwds):
    resource = acquire_resource(*args, **kwds)
    try:
        yield resource
    finally:
        release_resource(resource)

It seems to me, however, that this will do the exact same thing:

@contextmanager
def managed_resource(*args, **kwds):
    resource = acquire_resource(*args, **kwds)
    yield resource
    release_resource(resource)

I’m sure I must be missing something. What am I missing?

Asked By: Kris

||

Answers:

Because a finally statement is guaranteed to run no matter what (except a power outage), before the code can terminate. So writing it like this guarantees that the resource is always released

Answered By: oskros

finally makes sure that the code under it is always executed even if there’s an exception raised:

from contextlib import contextmanager

@contextmanager
def exception_handler():
    try:
        yield
    finally:
        print("cleaning up")

with exception_handler():
    result = 10 / 0

If there were no try-finally, the above example wouldn’t cleanup itself afterwards.

Answered By: ritiek