On 11/26/14, Nick Coghlan wrote: > On 26 November 2014 at 04:04, Guido van Rossum <gu...@python.org> wrote: > > On Tue, Nov 25, 2014 at 9:49 AM, Chris Angelico <ros...@gmail.com> wrote: > >> > >> On Wed, Nov 26, 2014 at 4:45 AM, Isaac Schwabacher > >> <ischwabac...@wisc.edu> wrote: > >> > Yield can also raise StopIteration, if it's thrown in. The current > >> > interaction of generator.throw(StopIteration) with yield from can't be > >> > emulated under the PEP's behavior, though it's not clear that that's a > >> > problem. > >> > > >> > >> Hrm. I have *absolutely* no idea when you would use that, and how > >> you'd go about reworking it to fit this proposal. Do you have any > >> example code (production or synthetic) which throws StopIteration into > >> a generator? > > > > > > Sounds like a good one for the obfuscated Python contest. :-) > > > > Unless the generator has a try/except surrounding the yield point into which > > the exception is thrown, it will bubble right out, and PEP 479 will turn > > this into a RuntimeError. I'll clarify this in the PEP (even though it > > logically follows from the proposal) -- I don't think there's anything to > > worry about. > > This is actually the edge case that needs to be handled in contextlib > - a StopIteration raised by the with statement body gets thrown into > the generator implementing the context manager. My current porting > recommendation is to catch the RuntimeError & look at __cause__ to see > if it's the StopIteration instance that was thrown in, but an > alternative option would be to just call gen.close() in that case, > rather than gen.throw(exc).
This actually leads to a good example of why the PEP is necessary: ``` In [1]: import contextlib In [2]: @contextlib.contextmanager ...: def transact(): ...: print('setup transaction') ...: try: ...: yield from subgenerator() ...: except: ...: print('rollback transaction') ...: raise ...: else: ...: print('commit transaction') ...: finally: ...: print('clean up transaction') ...: In [3]: def subgenerator(): ...: print('setup subgenerator') ...: try: ...: yield ...: except: ...: print('subgenerator failed') ...: raise ...: else: ...: print('subgenerator succeeded') ...: finally: ...: print('clean up subgenerator') ...: In [4]: with transact(): ...: next(iter([])) ...: setup transaction setup subgenerator subgenerator failed clean up subgenerator commit transaction # BAD NOT GOOD BIG FAIL clean up transaction ``` ijs _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com