# More Pythonic Context Manager Wrapper

I wanted to ask this here because what I wanted to originally do felt like a really Pythonic method. I want to be able to use the syntax:

d = {'apple':{'cranberry':{'banana':{'chocolate':[1,2,3,4,5,6]}}},'b':2}
with d['apple']['cranberry']['banana']['chocolate'] as item:
for i in item:
print(i)

item.append('k')


but found that Python doesn't allow for using lists, dicts, etc. as context managers.

So I implemented my own:

def context_wrap(target):
class ContextWrap:
def __init__(self, tgt):
self._tgt = tgt

def __enter__(self):
return self._tgt

def __exit__(self, type, value, traceback):
pass

return ContextWrap(target)

if __name__ == '__main__':
with context_wrap({'a':1}) as item:
print(item['a'])

with context_wrap([1,2,3,4,5]) as item:
print(item[1])

with context_wrap(3) as item:
print (item)


In the above code, you can take any random object and wrap it inside an object that acts as a context manager controlling the underlying object. This means that inside any with clause, you can simply use the object with it's alias. I feel like it looks a lot cleaner and clearer than something like:

alias = d['apple']['cranberry']['banana']['chocolate']
for i in alias:
print(i)

alias.append('k')


I wanted to know if there was a more "Pythonic" way to do it. So the improvement that I'm looking for is in terms of better reliance on the standard Python library and/or in terms of my syntax.

• What's the advantage of this over just saying item = d['a']? Usually the purpose of a context manager is to do something in the __exit__ (close a file, free a resource, etc) but your use case doesn't require anything like that. Feb 26 '20 at 23:59
• Welcome to code review, the question might be better received if the title was something like Context Manager Wrapper and there was a paragraph explaining what the code does. Feb 27 '20 at 0:23
• @pacmaninbw Let me amend my post. Feb 27 '20 at 0:25
• @SamStafford This is going to be used for more complicated objects where you wouldn't want to just endlessly list the same parameters over and over. Something like d = {'a':{'b':{'c':{'d':'e'}}}} where the object is complex/deeply nested. Feb 27 '20 at 0:25
• You might want to read the guidelines for good questions at codereview.stackexchange.com/help/how-to-ask. Feb 27 '20 at 0:30

I think what you are doing is crazy, but yes, you can use Python’s library functions to clean it up.

from contextlib import contextmanager

@contextmanager
def context_wrap(target):
yield target


Again, this is busy work.

alias = thing


is clearer, shorter and faster than

with context_wrap(thing) as alias:

• Wow, this is extremely much cleaner than my solution. And I can see a few uses for it! Using a context manager doesn't leave a strong reference around in case something needs to be cleaned up by the garbage collector! I think it's especially useful for classes. Feb 27 '20 at 16:55
• alias will still be equal to thing after the with statement exits. It doesn't remove the variable, so a strong reference will still exist! Feb 27 '20 at 17:11
• I think I have some more work to do then. But thanks for the help anyway! Feb 27 '20 at 18:06
• Trying to trick the Python garbage collector into cleaning things up at specific times is not going to be a fun game to play. Write it in Rust if object lifetimes are that important! :) Feb 27 '20 at 18:41