shaoyl85 shaoyl85 - 4 years ago 178
Python Question

Context Manager without Yield

Can I have a context manager which occasionally does not yield, and in which case the code within the with statement are simply not executed?

import contextlib

def MayNotYield(to_yield):
if to_yield:

with MayNotYield(True):
print 'This works.'

with MayNotYield(False):
print 'This errors.'

I could ask the user to wrap the with statement with a try-catch, but that is not preferred. I could also do the following but it is ugly too.

import contextlib

def AlwaysYields(to_yield):
if to_yield:
yield 1
yield 2

with AlwaysYields(True) as result:
if result == 1:
print 'This works.'


As a conclusion, the answer is that the "with" statement does not have an option to skip the body. Whatever the
does, as long as
does not throw an exception, the body will always be executed. However, the post Python context manager: conditionally executing body? provided a few hacky ways as workaround. In particular, the user could use the
statement instead.

Answer Source

Unfortunately, the context manager protocol does not give a context manager a way to say "Don't run the with block" (except raising an exception in __enter__). If you're using a context manager anyway, I think your second approach, which has __enter__ return a value to signal if the block should be run is the best approach. If you don't need a context manager for some other reason, you could just use a simple if statement:

if do_stuff:
    # do the stuff
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download