coroutine, throw, yield, call-stack and exception handling

Ian Kelly ian.g.kelly at gmail.com
Mon Feb 8 16:56:55 EST 2016


On Mon, Feb 8, 2016 at 2:17 AM, Veek. M <vek.m1234 at gmail.com> wrote:
> ****************************
> Exceptions can be raised inside a coroutine using the throw(
>
> Exceptions raised in this manner will originate at the currently
> executing yield state-ment in the coroutine.A coroutine can elect to
> catch exceptions and handle them as appropriate. It is not safe to use
> throw() as an asynchronous signal to a coroutine—it should never be
> invoked from a separate execution thread or in a signal handler.
> ****************************
>
> What does Beazley mean by this: 'will originate at the currently
> executing yield state-ment in the coroutine'
>
> If he's throw'ing an exception surely it originates at the throw:
>
> def mycoroutine():
>  while len(n) > 2:
>    n = (yield)
>
>  throw('RuntimeError' "die!")

The "throw" is not called from inside the coroutine. It's a method of
the generator object, and it's used by the calling code. It's similar
to calling the send method, except that instead of passing a value to
be returned by the yield expression, it passes an exception to be
raised inside the coroutine at the yield expression.

Example:

def mycoroutine():
  n = 0
  while True:
    try:
      n = (yield n)
    except SomeException:
      n = 42

coro = mycoroutine()
coro.next()
for i in range(100):
  if i % 6 == 0:
    coro.send(i % 6)
  else:
    coro.throw(SomeException())


> Also this bit:
> ***********************
> If a coroutine returns values, some care is required if exceptions
> raised with throw() are being handled. If you raise an exception in a
> coroutine using throw(), the value passed to the next yield in the
> coroutine will be returned as the result of throw(). If
> you need this value and forget to save it, it will be lost.
> ***********************
>
> def coroutine():
>   while True:
>    line = (yield result)
>
>   throw(FooException)
>
> where is the question of a 'yield'? You'll exit the coroutine straight
> away..

Taking my example from above, after SomeException is caught, the next
value yielded inside the coroutine will be the return value of the
coro.throw() call. This may be surprising if you're only expecting
coro.send() and not coro.throw() to return yielded values.


More information about the Python-list mailing list