[Python-ideas] An async facade?

Jonathan Slenders jonathan at slenders.be
Thu Dec 20 23:52:27 CET 2012


Hi All,

This week I finished some Python syntax on a Pypy fork. It was an
experiment I was working on this week. We really needed a cleaner way of
writing asynchronous code. So, instead of using the yield keyword and an
@async decorator, we implemented the 'await' keyword, similar to c#.

So, because I just now subscribed to python-ideas, I cannot reply
immediately to the following thread:

An async facade? (was Re: [Python-Dev] Socket timeout and completion based
sockets)


Anyway, like c# does, I implemented the await keyword for Python, and
should say that I'm really confident of the usability of the result.
Personally,
I think this is a very clean solution for Twisted's @defer.inlineCalbacks,
Tornado's @gen.engine, and similar functions in other async frameworks. We
use it right now in a commercial web environment, where third party users
should have to be able to write asynchronous code as easy as possible in a
web based IDE.

https://bitbucket.org/jonathanslenders/pypy

Two interpreter hooks were added: (both accept a callable as parameter.)

>>>> sys.setawaithandler(wrapper)
>>>> sys.setawaitresultwrapper(result_wrapper)


The first will set the I/O scheduler  a functions for wrapping others
functions which contain 'await' instead of 'yield'. This wrapper function
will receive a generator as input. So, 'await' still acts like 'yield' for
the interpreter, but the result is automatically wrapped by this function,
if the await keyword was found.

The second function will wrap the return result of asynchronous functions.
So, unlike normal generators with 'yield' keywords, where 'await' has been
used, we still can return a result. But this result will be wrapped by this
function, so that the generator in the scheduler  will be able
te recognize the returned result.

This:

@defer.inlineCallbacks
def async_function(deferred_param):
    a = yield deferred_param
    b = yield some_call(a)
    yield defer.returnValue(b)


will now become:

def async_function(deferred_param):
    a = await deferred_param
    b = await some_call(a)
    return b


So, while still being explicit, it requires minimal syntax, and
allows distinguishing between when to 'wait' for an asynchronous task, and
when to pass the Future object around.

I really have no idea whether this has been proposed before, I can only say
that we are using it and it works pretty well.

Cheers,
Jonathan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20121220/fc67b368/attachment.html>


More information about the Python-ideas mailing list