New submission from Hannan Aharonov: If the code that defines a context manager performs some operations on a generator that cause it to raise StopIteration, this exception is propagated to the context manager's __exit__() method and there swallowed by a try..except block.
This can cause unexpected/unintuitive behaviour. The following simplified example shows an infinite loop caused by this: ------- from contextlib import contextmanager @contextmanager def manager(gen): yield gen.next() emptygen = (_ for _ in ()) while True: with manager(emptygen): print "Infinite Loop" ------- In this case, even though the generator is empty, the loop will never stop, because the generator's StopIteration exception is swallowed by the context manager. (If `gen.next()` was wrapped by try..except that reraises exception as, say, RuntimeError, the program would stop.) I've looked at the source (here: http://hg.python.org/cpython/file/tip/Lib/contextlib.py line 67) and I understand why this is happening: the context manager can't tell the difference between the two kinds of StopIteration - one that is raised by its own completion, and one that is raised by a call in its body. I don't know if this is a bug or expected behavior of nested generators. In any case, I haven't seen this issue mentioned in the documentation, and the behavior is unintuitive. I've searched the bug tracker and found a similar issue that handled swallowing of StopIteration in the code wrapped by the context manager (http://bugs.python.org/issue1705170), and another similar issue (http://bugs.python.org/issue16610) that was closed without resolution. ---------- components: Interpreter Core, Library (Lib) messages: 217421 nosy: hannan.aha, ncoghlan priority: normal severity: normal status: open title: StopIteration is silenced when raised by generator within context manager versions: Python 2.7 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue21379> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com