I have no right to speak because I haven't read through all the details of the proposal, but reading this I am very sad that we have to introduce a whole new exception (and one with special status as well) in order to fix such a niggly corner case of the context manager protocol.
Since IIUC the original context manager design was intended to have exactly one yield in the body of the context manager -- can't we just declare fewer (or more) yields an error and rase an appropriate TypeError or something? --Guido On Mon, Mar 16, 2009 at 4:43 AM, Nick Coghlan <ncogh...@gmail.com> wrote: > Michael Foord wrote: >> Well, StopIteration is still an implementation detail that only >> occasionally bleeds through to actual programming. It says nothing about >> whether using exceptions for non-exceptional circumstances (control >> flow) is good practise. Personally I think it makes the intent of code >> less easy to understand - in effect the exceptions *are* being used as a >> goto. > > Note that raising SkipStatement manually is likely to be even rarer than > raising StopIteration. Catching it should almost never happen other than > implicitly inside a with statement (that's the reason I made it a peer > of SystemExit and GeneratorExit rather than a peer of StopIteration). > > It is primarily proposed as a way for contextlib.contextmanager to tell > the interpreter that the underlying generator didn't yield, so the body > of the with statement should be skipped completely. It just so happens > that manually implemented context managers will also be free to use it > if they need to for some reason. > > An alternative approach worth considering may be to use NotImplemented > as a model instead of StopIteration. With that approach, instead of > having SkipStatement be an exception, have it be a singleton that can be > returned from __enter__ to indicate that the with statement body would > be skipped. > > That has a big advantage over using an exception when it comes to > execution speed. The statement semantics in that case would become: > > mgr = (EXPR) > exit = mgr.__exit__ # Not calling it yet > value = mgr.__enter__() > if value is not SkipStatement: > exc = True > try: > try: > VAR = value # Only if "as VAR" is present > BLOCK > except: > # The exceptional case is handled here > exc = False > if not exit(*sys.exc_info()): > raise > # The exception is swallowed if exit() returns true > finally: > # The normal and non-local-goto cases are handled here > if exc: > exit(None, None, None) > > (keeping in mind that I already plan to change PEP 377 to drop the idea > of assigning anything to VAR when the statement body is skipped) > > The major drawback of that approach is that it becomes a little trickier > to write a context manager like nested() correctly - it would need to > check all of the __enter__() return values and start unwinding the > context manager stack if it encountered SkipStatement. The fix isn't > particularly complicated*, but it does contrast with the fact that > having SkipStatement as an exception means that the current > implementation of nested() will "just work" with the new semantics. > > Cheers, > Nick. > > * For reference, to support a "SkipStatement as return value" approach > the main loop in nested() would have to change from this: > > for mgr in managers: > exit = mgr.__exit__ > enter = mgr.__enter__ > vars.append(enter()) > exits.append(exit) > yield vars > > To this: > > for mgr in managers: > exit = mgr.__exit__ > enter = mgr.__enter__ > var = enter() > if var is SkipStatement: > break > vars.append(var) > exits.append(exit) > else: > yield vars > > As mentioned above, if SkipStatement is an exception then nested() works > correctly without any changes. > > -- > Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia > --------------------------------------------------------------- > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > http://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > http://mail.python.org/mailman/options/python-dev/guido%40python.org > -- --Guido van Rossum (home page: http://www.python.org/~guido/) _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com