Greenlet Support¶
Pulsar greenio
facilitates the integration of synchronous
third-party libraries into pulsar asynchronous framework.
It requires the greenlet library.
If you want to understand how integration works but you are unfamiliar with greenlets, check out the greenlet documentation first.
Note
pulsar-odm is a separate library, maintained by the same authors of pulsar, which provides asynchronous object data mapping with asyncio and sqlalchemy and uses pulsar greenio extensions.
This application does not use monkey patching and therefore it works quite differently from implicit asynchronous libraries such as gevent. This module provides the user with a set of utilities for explicitly transferring execution from one greenlet to another which executes the blocking call in a greenlet-friendly way.
The caller has the responsibility that the blocking call is greenlet-friendly, i.e. it transfers the control of execution back to the parent greenlet when needed.
Usage¶
Lets assume you are building an application which uses pulsar asynchronous engine and would like to
- either use an external library written in blocking style, i.e. without yielding control to the event loop when IO calls are performed.
- or write your client code without dealing with
Future
or coroutines, in other words in an implicit asynchronous style. In this way your client code can be used on other frameworks just as well.
In both cases, the greenio
application is what you need.
Green WSGI¶
Assume you are using pulsar web server and would like to write your application
in an implicit asynchronous mode, i.e. without dealing with futures nor
coroutines, then you can wrap your WSGI app
with the GreenWSGI
utility:
from pulsar.apps.wsgi import WSGIServer
from pulsar.apps.greenio import GreenPool, GreenWSGI
green_pool = greenio.GreenPool()
callable = GreenWSGI(app, green_pool)
WSGIServer(callable=callable).start()
The GreenPool
manages a pool of greenlets which execute your
application. In this way, within your app
you can invoke the
wait()
function when needing to wait for asynchronous results to be
ready.
GreenHttp¶
The HttpClient
can be used with greenlets:
>>> from pulsar.apps.greenio import GreenHttp
>>> http = GreenHttp()
And now you can write synchronous looking code and run it in a separate
greenlet via the run_in_greenlet()
decorator:
@greenio.run_in_greenlet
def example():
response = http.get('http://bbc.co.uk')
...
return response.text()
and somewhere, in your asynchronous code:
result = await example()
result == ...
the run_in_greenlet()
decorator, execute the function on a child
greenlet without blocking the asynchronous engine. Once the example
function returns, the asynchronous code continue from the yield
statement as usual.
API¶
Wait¶
Run in greenlet¶
Green Pool¶
-
class
pulsar.apps.greenio.pool.
GreenPool
(max_workers=None, loop=None)[source]¶ A pool of running greenlets.
This pool maintains a group of greenlets to perform asynchronous tasks via the
submit()
method.-
closed
¶ True if this pool is closed and no task can queued
-
in_green_worker
¶ True if the current greenlet is a green pool worker
-
Green Lock¶
-
class
pulsar.apps.greenio.lock.
GreenLock
(loop=None)[source]¶ A Locking primitive that is owned by a particular greenlet when locked.The main greenlet cannot acquire the lock.
A primitive lock is in one of two states, ‘locked’ or ‘unlocked’.
It is created in the unlocked state. It has two basic methods,
acquire()
andrelease()
. When the state is unlocked,acquire()
changes the state to locked and returns immediately.When the state is locked,
acquire()
blocks the current greenlet until a call torelease()
changes it to unlocked, then theacquire()
call resets it to locked and returns.