On Sun, Nov 06, 2016 at 06:46:40AM +0200, Ram Rachum wrote: > Hi everyone, > > Here is a simplification of a problem that's been happening in my code: > > import contextlib > > @contextlib.contextmanager > def f(): > print('1') > try: > yield > finally: > print('2') > > > g = f() > g.__enter__() > > > This code prints 1 and then 2, not just 1 like you might expect.
I expect it to print 2. After all, its in a finally clause. And why are you calling g.__enter__() directly? Calling dunder methods by hand is nearly always the wrong thing to do. > This is > because when the generator is garbage-collected, it gets `GeneratorExit` > sent to it. Right. That's what they're designed to do. Later, in another thread you say: "Well, you think it's weird that I want a `finally` clause to not be called in some circumstances. Do you think it's equally weird to want an `__exit__` method that is not called in some circumstances?" Yes to both. It is seriously weird. You might as well be complaining that Python calls your __iter__ method when you call iter(my_instance). That's the whole point of __iter__, and the whole point of finally clauses and the __exit__ method is that they are unconditionally called, always, when you leave the with block. But judging from your code above, it looks like you're not even using a with block. In that case, instead of abusing the __enter__ and __exit__ methods, why not just create a class with non-dunder enter() and exit() methods and call them by hand? g = f() # implementation of f is left as an exercise g.enter() if condition: g.exit() I'm having a lot of difficulty in understanding your use-case here, and so maybe I've completely misunderstood something. > This has been a problem in my code since in some instances, I tell a > context manager not to do its `__exit__` function. (I do this by using > `ExitStack.pop_all()`. However the `__exit__` is still called here. Have you considered something like: def f(): print('1') try: yield finally: if f.closing: print('2') You can then write a decorator to set f.closing to True or False as needed. But again, I don't understand why you would want this feature, or how you are using it, so I might have this completely wrong. -- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/