I am having a hard time to write clean code with context managers in Python without getting in a context manager hell. Imagine something like: class A: def __init__(self): self.b = B() # where B is a context manager This leaks now, because I did not use a with statement. In the wild I have seen two solutions to this: Inject B in the class and have some outer with statement with B() as b: a = A(b) Make A a context manager as well that implements closing B: with A() as a: ... # A will close B now in its __exit__ method I dislike both methods. In my example the usage of B inside of A is an implementation detail. It is not something I want to expose to the outer world. Thus, Option 1 is obviously not suitable, but even Option 2 exposes some details. Mainly that A does some resource management. Additionally having to manually implement the __exit__ method does seem to defeat a little bit the purpose of B being a context manager, if I cannot use the context manager syntax. So I am sort of missing the C++ RAII here I think, which is not directly suitable for Python. So how can I avoid making basically all my classes context managers if there is a dependency chain? To give a very concrete use case: An ML agent (like ChatGPT) wants to execute code. So I might have a class Agent that can execute code. This is done with jupyter notebook. Thus my program needs a jupyter notebook server running. Ideally I would like to encapsulate this within the Agent class. The Agent class starts the server and stops the server. The server here is implemented as a context manager. The solution I would come up with is making the Agent now a context manager too, which I dislike. Because then some class using the Agent needs to become a context manager too, ... so in the end my whole program is a context manager. Continue reading...