Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

@contextlib.contextmanager
def MayNotYield(to_yield):
  if to_yield:
    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

@contextlib.contextmanager
def AlwaysYields(to_yield):
  if to_yield:
    yield 1
  else:
    yield 2

with AlwaysYields(True) as result:
  if result == 1:
    print 'This works.'
like image 551
shaoyl85 Avatar asked Dec 29 '15 21:12

shaoyl85


People also ask

What does yield do in context manager?

yield expression returns control to the whatever is using the generator. The generator pauses at this point, which means that the @contextmanager decorator knows that the code is done with the setup part.

When would you use a context manager?

A context manager usually takes care of setting up some resource, e.g. opening a connection, and automatically handles the clean up when we are done with it. Probably, the most common use case is opening a file. The code above will open the file and will keep it open until we are out of the with statement.

Which methods are required to implement context management protocol?

Context managers can be written using classes or functions(with decorators). Creating a Context Manager: When creating context managers using classes, user need to ensure that the class has the methods: __enter__() and __exit__().


1 Answers

Another option would be to just use a regular generator rather than a contextmanager; a plain generator won't have this restriction. But you'll have to use it with a "for" construct rather than using "with":

def MayNotYield(to_yield):
   if to_yield:
      yield

for _ in MayNotYield(True):
   print('This prints.')

for _ in MayNotYield(False):
   print('This does not.')
like image 83
dmattp Avatar answered Sep 20 '22 04:09

dmattp