[Python-ideas] Async API

Yury Selivanov yselivanov.ml at gmail.com
Tue Oct 30 02:59:56 CET 2012


Guido, Greg,

On 2012-10-27, at 7:45 PM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:

> Right.  But now I'm not sure this approach will work with yield-froms.
> As when you yield-fromming scheduler knows nothing about the chain of 
> generators, as it's all hidden in the yield-from implementation.

I think I've come up with a solution that should work for yield-froms too
(if we accept my in_finally idea in 3.4).  And there should be a way
of writing a 'protect_finally' context manager too.

I'll illustrate the approach on Guido's tulip micro-framework
(consider it a pseudo code to illustrate the idea):

    class Interrupt(BaseException):
        """Should penetrate all try..excepts"""

    def call_with_timeout(timeout, gen):
        context.current_task._add_timeout(timeout, gen)
        try:
            return (yield from gen)
        except Interrupt:
            raise TimeoutError() from None

    class Task:
        def _add_timeout(timeout, gen):
            self.eventloop.call_later(
                timeout,
                partial(self._interrupt, gen))

        def _interrupt(self, gen):
            if not gen.in_finally:
                gen.throw(Interrupt, Interrupt(), None)
            else:
                # So we set a flag to watch for gen's in_finally value
                # on each 'step' call.  And when it's 0 - Task.step
                # will call '_interrupt' again.
                self._watch_finally(gen)

I defined a new function 'call_with_timeout', because tulip's 'with_timeout'
starts a new Task, whereas the former works in any generator inside the task.

So, after that you'd be able to do the following:

     yield from call_with_timeout(1.0, something())

And something's 'finally' won't ever be aborted.

-
Yury



More information about the Python-ideas mailing list