I have a long-running process called an Updater, that has updates (to an ETL system) submitted to it. The updates have resource requirements that are managed by adding a context manager to the Updater's ExitStack. Some updates will include new configuration, which means that effected resources must be released from the stack and a newly configured version of the resource will be added. I need something like:
with ExitStack() as stack:
ctx_manager = open("file.txt")
f = stack.enter_context(ctx_manager)
...
ctx_pop(ctx_manager, stack) # remove the given context manager from the stack
Below is an example of something I've gotten to work, but it relies on accessing protected members. I was hoping there might be a less 'dirty' solution than this:
def ctx_pop(cm, stack):
for item in stack._exit_callbacks:
if item.__self__ is cm:
break
else:
raise KeyError(repr(cm))
stack._exit_callbacks.remove(item)
item(None, None, None)
Edit: Added known solution
ExitStack
uses adeque
to store wrappers for the contexts.__exit__
method so you would need to be able to identify the wrapper by the original context manager which, as far as I know, isn't possible. You may need to reinvent (at least partially) the functionality ofExitStack
to be able to remove contexts ahead of time. – ArcheozoicExitStack
objects in a Jupyter Notebook. They have a deque of closures who's__self__
attribute is a context manager. I'll put some code up as an known solution, but I was hoping for a less 'hack' solution. I wanted to see if there was a cleaner solution before I submit to Python Ideas or add it myself (which I've never done before). – Protocol