I'm trying to write a context manager that uses other context managers, so clients don't need to know the whole recipe, just the interface I'm presenting. I can't do it using @contextmanager
- the code after yield
call doesn't get executed if you're interrupted by an exception, so I need to use a class-based manager.
Here's a little example script:
from contextlib import contextmanager
import pprint
d = {}
@contextmanager
def simple(arg, val):
print "enter", arg
d[arg] = val
yield
print "exit", arg
del d[arg]
class compl(object):
def __init__(self, arg, val):
self.arg=arg
self.val=val
def __enter__(self):
with simple("one",1):
with simple("two",2):
print "enter complex", self.arg
d[self.arg] = self.val
def __exit__(self,*args):
print "exit complex", self.arg
del d[self.arg]
print "before"
print d
print ""
with compl("three",3):
print d
print ""
print "after"
print d
print ""
That outputs this:
before
{}
enter one
enter two
enter complex three
exit two
exit one
{'three': 3}
exit complex three
after
{}
I want it to output this:
before
{}
enter one
enter two
enter complex three
{'one': 1, 'three': 3, 'two': 2}
exit complex three
exit two
exit one
after
{}
Is there any way to tell a class-based context manager to wrap itself with other context managers?
Yes, the context manager will be available outside the with statement and that is not implementation or version dependent. with statements do not create a new execution scope.
Python provides an easy way to manage resources: Context Managers. The with keyword is used. When it gets evaluated it should result in an object that performs context management. Context managers can be written using classes or functions(with decorators).
The with statement in Python is used for resource management and exception handling. You'd most likely find it when working with file streams. For example, the statement ensures that the file stream process doesn't block other processes if an exception is raised, but terminates properly.
@contextmanager
def compl(arg, val):
with simple("one",1):
with simple("two",2):
print "enter complex", arg
try:
d[arg] = val
yield
finally:
del d[arg]
print "exit complex", arg
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With