The other option is to wrap just the application function, and use
async.coroutines for all else.
I'm sure there are subtleties that I don't understand and will break this stuff.
def async_app(f):
def _application(environ, start_response):
status, headers = None, None
def _start_response(s, h):
nonlocal status, headers
status, headers = s, h
# wrap the function in a asyncio coroutine, then run it as a
Task (which returns an asyncio future)
co = asyncio.coroutine(f)
future = asyncio.async(co(environ, _start_response))
# then do the greenlet dance
myself = greenlet.getcurrent()
future.add_done_callback(lambda _: myself.switch()) # goes back
to the suspended call, one line below
myself.parent.switch() # this
suspends the greenlet. goes to the event loop
# return the result of the function
start_response(status, headers)
return future.result()
return _application
@async_app
def application(environ, start_response):
start_response('200 OK', [('Content-Type','text/html')])
response = yield from sleeping()
return [response]
On 1 February 2015 at 22:20, Damjan Georgievski <[email protected]> wrote:
> Reading about asyncio in uwsgi at
> http://uwsgi-docs.readthedocs.org/en/latest/asyncio.html
>
> I really didn't like the ugly explicit switching, passing the greenlet
> around and the future. So I made this simple decorator that hides that
> away:
>
> def coroutine(f):
>
> def _f(*args, **kwargs):
> myself = greenlet.getcurrent()
> co = asyncio.coroutine(f)
> future = asyncio.async(co(*args, **kwargs))
>
> future.add_done_callback(lambda _: myself.switch()) # goes back
> to the suspended call, one line below
> myself.parent.switch() # suspends.
> goes to the event loop
>
> return future.result()
>
> return _f
>
> So it takes the wrapped function, wraps it in a asyncio.coroutine,
> sets it for running as a Task (which returns a future), registers a
> callback on the future to switch back the greenlet, and switches away
> the greenlet. When the greenlet gets switched back to, it gets the
> result of the future and returns that.
>
> @coroutine wrapped functions still need to use 'yield from' of course,
> since they are still asyncio coroutines.
>
> Usage is like this:
>
> @coroutine
> def sleeping():
> yield from asyncio.sleep(2)
> return b'test'
>
> def application(environ, start_response):
> start_response('200 OK', [('Content-Type','text/html')])
> response = sleeping()
> return [response]
>
>
> --
> damjan
--
damjan
_______________________________________________
uWSGI mailing list
[email protected]
http://lists.unbit.it/cgi-bin/mailman/listinfo/uwsgi