Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Gevent

Introduction to Gevent

A gentle introduction to Gevent (http://gevent.org/)

Isman Firmansyah

August 31, 2013
Tweet

More Decks by Isman Firmansyah

Other Decks in Programming

Transcript

  1. WHAT IS GEVENT gevent is a -based Python networking library

    that uses to provide a high-level synchronous API on top of the event loop. coroutine greenlet libevent
  2. COROUTINE TL;DR http://en.wikipedia.org/wiki/Coroutine or in a nutshell: Well, a coroutine

    is a subroutine or function that can pause in the middle and return a value. When you call it again it picks up right where it was when you paused, environment intact, and keeps on going. http://is.gd/J2Zq0R
  3. CONCURRENCY DOES MATTER Concurrency is the composition of independently executing

    computations. It simulates the real-world. → Optimize performance and scalability. → http://is.gd/G0ewD8 http://is.gd/IsYrKF
  4. CONCURRENT.FUTURES Mimic of Java's concurrent.futures Available in Python 3.2+ Backport

    for Python 2.5 - 3.1 → https://pypi.python.org/pypi/futures
  5. WHY NOT X - - - - - ... PyPy

    NodeJS Erlang Elixir Go Let's talk after this session ends :)
  6. SYNCHRONOUS API Write program that looks blocking, but actually runs

    asynchronously. # blocking for x in xrange(1, 11): time.sleep() # non-blocking ops = [] for x in xrange(1, 11): ops.append(gevent.spawn(time.sleep)) gevent.joinall(ops)
  7. NO CALLBACK-WORRIES Forget the callback!! def _collection_handler(self, callback=None, on_error=None): def

    inner(fd, ev): try: self._db.read_query_result() resultset = self._db.use_result() rows = self._get_rows(resultset) if callback: callback(rows) except Exception, exc: self._throw_error(exc, on_error) finally: self._ioloop.remove_handler(self._db.fd) return inner
  8. MONKEY PATCHING UTILITY Patches stdlib and 3rd-party modules to become

    cooperative. import gevent.monkey gevent.monkey.patch_all() ops = [] for x in xrange(1, 11): ops.append(gevent.spawn(time.sleep)) gevent.joinall(ops) Caveats: cannot be used for C-extension
  9. HUGE COLLECTIONS OF COMPATIBLE LIBRARIES Thanks to monkey patching, we

    have abundant async libraries: MySQL => pymysql/ultramysql Redis => redis-py Beanstalk => beanstalkc Postgres => psycopg (with specific setup) ... and more
  10. TOOLS BUILT ON TOP/SUPPORTS GEVENT / : load testing :

    Python implementation of the Socket.IO : Requests + Gevent : WSGI server ... and more locust.io boom gevent-socketio grequests gunicorn
  11. SPAWNING GREENLET import gevent from gevent import Greenlet def foo(message,

    n): gevent.sleep(n) print message # Initialize a new Greenlet instance running the named function foo thread1 = Greenlet.spawn(foo, "Hello", 1) # Wrapper for Greenlet.spawn thread2 = gevent.spawn(foo, "I live!", 2) threads = [thread1, thread2] # Block until all threads complete. gevent.joinall(threads)
  12. MONITORING GREENLET Use Greenlet states: started, ready, successful(), value, and

    exception. Mostly, you'll only need value and exception.
  13. RETRIEVING THE VALUE FROM A GREENLET Use greenlet.value: import gevent

    def win(): return 'You win!' if __name__ == "__main__": winner = gevent.spawn(win) gevent.joinall([winner]) print "winner value:", winner.value # "You win!"
  14. HANDLING EXCEPTION Use greenlet.exception: import gevent def fail(): raise Exception('You

    fail at failing.') if __name__ == "__main__": loser = gevent.spawn(fail) # Exceptions raised in the Greenlet, stay inside the Greenlet. try: gevent.joinall([loser]) except Exception as exc: print "This will never be reached!" # It is possible though to raise the exception again outside #raise loser.exception # Or using #loser.get() # A stack trace will be printed to stdout but it # will not unwind the stack of the parent. print "loser exception:", loser.exception
  15. WITHOUT GEVENT import time def boring(): print "without gevent" for

    x in xrange(1, 11): print "boring!", x time.sleep(1) if __name__ == "__main__": boring()
  16. WITH GEVENT import gevent.monkey gevent.monkey.patch_all() import time def green(): print

    "with gevent" ops = [] for x in xrange(1, 11): print "boring!", x ops.append(gevent.spawn(time.sleep)) gevent.joinall(ops) if __name__ == "__main__": green()