Async with Gevent

gevent is recommended for doing asynchronous I/Owith Postgresql or MySQL. Reasons I prefer gevent:

  • No need for special-purpose “loop-aware” re-implementations of everything.Third-party libraries using asyncio usually have to re-implement layers andlayers of code as well as re-implementing the protocols themselves.
  • Gevent allows you to write your application in normal, clean, idiomaticPython. No need to litter every line with “async”, “await” and other noise.No callbacks, futures, tasks, promises. No cruft.
  • Gevent works with both Python 2 and Python 3.
  • Gevent is Pythonic. Asyncio is an un-pythonic abomination.

Besides monkey-patching socket, no special steps are required if you are usingMySQL with a pure Python driver like pymysqlor are using mysql-connectorin pure-python mode. MySQL drivers written in C will require specialconfiguration which is beyond the scope of this document.

For Postgres and psycopg2, which is a Cextension, you can use the following code snippet to register event hooks thatwill make your connection async:

  1. from gevent.socket import wait_read, wait_write
  2. from psycopg2 import extensions
  3.  
  4. # Call this function after monkey-patching socket (etc).
  5. def patch_psycopg2():
  6. extensions.set_wait_callback(_psycopg2_gevent_callback)
  7.  
  8. def _psycopg2_gevent_callback(conn, timeout=None):
  9. while True:
  10. state = conn.poll()
  11. if state == extensions.POLL_OK:
  12. break
  13. elif state == extensions.POLL_READ:
  14. wait_read(conn.fileno(), timeout=timeout)
  15. elif state == extensions.POLL_WRITE:
  16. wait_write(conn.fileno(), timeout=timeout)
  17. else:
  18. raise ValueError('poll() returned unexpected result')

SQLite, because it is embedded in the Python application itself, does notdo any socket operations that would be a candidate for non-blocking. Async hasno effect one way or the other on SQLite databases.