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

pulsar.apps.greenio.utils.wait(value, must_be_child=False)[source]

Wait for a possible asynchronous value to complete.

Run in greenlet

pulsar.apps.greenio.utils.run_in_greenlet(callable)[source]

Decorator to run a callable on a new greenlet.

A callable decorated with this decorator returns a coroutine

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

submit(func, *args, **kwargs)[source]

Equivalent to func(*args, **kwargs).

This method create a new task for function func and adds it to the queue. Return a Future called back once the task has finished.

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() and release(). 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 to release() changes it to unlocked, then the acquire() call resets it to locked and returns.

locked()[source]

‘Return the greenlet that acquire the lock or None.

acquire(timeout=None)[source]

Acquires the lock if in the unlocked state otherwise switch back to the parent coroutine.

release()[source]

Release the lock.

This method should only be called in the locked state; it changes the state to unlocked and returns immediately. If an attempt is made to release an unlocked lock, a RuntimeError will be raised.

Green WSGI

class pulsar.apps.greenio.wsgi.GreenWSGI(middleware, pool, response_middleware=None)[source]

Wraps a WSGI application to be executed on a GreenPool