The Gevent loop engine

Gevent is an amazing non-blocking Python network library built on top oflibev and greenlet. Even though uWSGI supports Greenlet assuspend-resume/greenthread/coroutine library, it requires a lot of effort andcode modifications to work with gevent. The gevent plugin requires gevent1.0.0 and uWSGI asynchronous/non-blocking modes (updated to uWSGI 1.9) mode.

Notes

  • The SignalFramework is fully working with Gevent mode. Each handlerwill be executed in a dedicated greenlet. Look at tests/ugevent.py foran example.
  • uWSGI multithread mode (threads option) will not work with Gevent.Running Python threads in your apps is supported.
  • Mixing uWSGI’s Async API with gevent’s is EXPLICITLY FORBIDDEN.

Building the plugin (uWSGI >= 1.4)

The gevent plugin is compiled in by default when the default profile is used.Doing the following will install the python plugin as well as the gevent one:

  1. pip install uwsgi

Building the plugin (uWSGI < 1.4)

A ‘gevent’ build profile can be found in the buildconf directory.

  1. python uwsgiconfig --build gevent
  2. # or...
  3. UWSGI_PROFILE=gevent make
  4. # or...
  5. UWSGI_PROFILE=gevent pip install git+git://github.com/unbit/uwsgi.git
  6. # or...
  7. python uwsgiconfig --plugin plugins/gevent # external plugin

Running uWSGI in gevent mode

  1. uwsgi --gevent 100 --socket :3031 --module myapp

or for a modular build:

  1. uwsgi --plugins python,gevent --gevent 100 --socket :3031 --module myapp

the argument of –gevent is the number of async cores to spawn

A crazy example

The following example shows how to sleep in a request, how to make asynchronousnetwork requests and how to continue doing logic after a request has beenclosed.

  1. import gevent
  2. import gevent.socket
  3.  
  4. def bg_task():
  5. for i in range(1,10):
  6. print "background task", i
  7. gevent.sleep(2)
  8.  
  9. def long_task():
  10. for i in range(1,10):
  11. print i
  12. gevent.sleep()
  13.  
  14. def application(e, sr):
  15. sr('200 OK', [('Content-Type','text/html')])
  16. t = gevent.spawn(long_task)
  17. t.join()
  18. yield "sleeping for 3 seconds...<br/>"
  19. gevent.sleep(3)
  20. yield "done<br>"
  21. yield "getting some ips...<br/>"
  22. urls = ['www.google.com', 'www.example.com', 'www.python.org', 'projects.unbit.it']
  23. jobs = [gevent.spawn(gevent.socket.gethostbyname, url) for url in urls]
  24. gevent.joinall(jobs, timeout=2)
  25.  
  26. for j in jobs:
  27. yield "ip = %s<br/>" % j.value
  28.  
  29. gevent.spawn(bg_task) # this task will go on after request end

Monkey patching

uWSGI uses native gevent api, so it does not need monkey patching. That said,your code may need it, so remember to call gevent.monkey.patch_all() at thestart of your app. As of uWSGI 1.9, the convenience option—gevent-monkey-patch will do that for you.Please note that uWSGI does monkey patching before your application starts,not before your application loads. So if you are loading other moduleswhile loading your application you may still need to callgevent.monkey.patch_all() yourself.

A common example is using psycopg2_gevent with django. Django will make aconnection to postgres for each thread (storing it in thread locals).

As the uWSGI gevent plugin runs on a single thread this approach will lead to adeadlock in psycopg. Enabling monkey patch will allow you to map thread localsto greenlets (though you could avoid full monkey patching and only callgevent.monkey.patch_thread()) and solves the issue:

  1. import gevent.monkey
  2. gevent.monkey.patch_thread()
  3. import gevent_psycopg2
  4. gevent_psycopg2.monkey_patch()

or (to monkey patch everything)

  1. import gevent.monkey
  2. gevent.monkey.patch_all()
  3. import gevent_psycopg2
  4. gevent_psycopg2.monkey_patch()

Notes on clients and frontends

  • If you’re testing a WSGI application that generates a stream of data, youshould know that curl by default buffers data until a newline. So make sureyou either disable curl’s buffering with the -N flag or have regularnewlines in your output.
  • If you are using Nginx in front of uWSGI and wish to stream data from yourapp, you’ll probably want to disable Nginx’s buffering.
  1. uwsgi_buffering off;