2

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?

Kris
  • 22,079
  • 3
  • 30
  • 35

2 Answers2

2

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

oskros
  • 3,101
  • 2
  • 9
  • 28
2

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.

ritiek
  • 2,477
  • 2
  • 18
  • 25