gevent is a coroutine-based Python networking library.
gevent 1.1 runs on Python 2 and Python 3. Version 2.7 of Python 2 is supported, and versions 3.3, 3.4, and 3.5 of Python 3 are supported. (Users of older versions of Python 2 need to install gevent 1.0.x (2.5) or 1.1.x (2.6); Python 3 is not supported by 1.0.) gevent requires the greenlet library.
gevent 1.1 also runs on PyPy 2.6.1 and above, although 5.0 or above is strongly recommended. On PyPy, there are no external dependencies.
gevent does not run on PyPy on Windows because the CFFI backend does not build.
gevent and greenlet can both be installed with pip, e.g.,
install gevent. On Windows and OS X, both gevent and greenlet are
distributed as binary wheels, so no C compiler is required (so long
as pip is at least version 8.0). On Linux or for Mac OS X variants
without pre-built wheels or if wheel installation is disabled, a C compiler
(Xcode on OS X) and the Python development package are required.
cffi can optionally be installed to build the CFFI backend in
addition to the Cython backend on CPython.
Some Linux distributions are now mounting their temporary
directories with the
noexec option. This can cause a
pip install gevent to fail with an error like
cannot run C compiled programs. One fix is to mount the
temporary directory without that option. Another may be to
--build option to
pip install to specify
another directory. See issue #570 and issue #612 for
Development instructions can be found on PyPI.
The following example shows how to run tasks concurrently.
>>> import gevent >>> from gevent import socket >>> urls = ['www.google.com', 'www.example.com', 'www.python.org'] >>> jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls] >>> gevent.joinall(jobs, timeout=2) >>> [job.value for job in jobs] ['18.104.22.168', '22.214.171.124', '126.96.36.199']
After the jobs have been spawned,
gevent.joinall() waits for
them to complete, allowing up to 2 seconds. The results are
then collected by checking the
gevent.socket.gethostbyname() function has the same
interface as the standard
socket.gethostbyname() but it does not
block the whole interpreter and thus lets the other greenlets proceed
with their requests unhindered.
The example above used
gevent.socket for socket operations. If the standard
module was used the example would have taken 3 times longer to complete because the DNS requests would
be sequential (serialized). Using the standard socket module inside greenlets makes gevent rather
pointless, so what about existing modules and packages that are built
on top of
socket (including the standard library modules like
That’s where monkey patching comes in. The functions in
replace functions and classes in the standard
socket module with their cooperative
counterparts. That way even the modules that are unaware of gevent can benefit from running
in a multi-greenlet environment.
>>> from gevent import monkey; monkey.patch_socket() >>> import urllib2 # it's usable from multiple greenlets now
Of course, there are several other parts of the standard library that can
block the whole interpreter and result in serialized behavior. gevent
provides cooperative versions of many of those as well. They can be
patched independently through individual functions, but most programs
using monkey patching will want to patch the entire recommended set of
modules using the
>>> from gevent import monkey; monkey.patch_all() >>> import subprocess # it's usable from multiple greenlets now
When monkey patching, it is recommended to do so as early as
possible in the lifetime of the process. If possible,
monkey patching should be the first lines executed. Monkey
patching later, especially if native threads have been
atexit or signal handlers have been installed,
or sockets have been created, may lead to unpredictable
results including unexpected
Instead of blocking and waiting for socket operations to complete (a technique known as polling), gevent arranges for the operating system to deliver an event letting it know when, for example, data has arrived to be read from the socket. Having done that, gevent can move on to running another greenlet, perhaps one that itself now has an event ready for it. This repeated process of registering for events and reacting to them as they arrive is the event loop.
Unlike other network libraries, though in a similar fashion as
eventlet, gevent starts the event loop implicitly in a dedicated
greenlet. There’s no
reactor that you must call a
dispatch() function on. When a function from gevent’s API wants to
block, it obtains the
gevent.hub.Hub instance — a special
greenlet that runs the event loop — and switches to it (it is said
that the greenlet yielded control to the Hub). If there’s no
Hub instance yet, one is automatically created.
Each operating system thread has its own
Hub. This makes it possible to use the
gevent blocking API from multiple threads (with care).
The event loop provided by libev uses the fastest polling mechanism available on the system by default. Please read the libev documentation for more information.
The Libev API is available under the
gevent.core module. Note that
the callbacks supplied to the libev API are run in the
greenlet and thus cannot use the synchronous gevent API. It is possible to
use the asynchronous API there, like
The greenlets all run in the same OS thread and are scheduled
cooperatively. This means that until a particular greenlet gives up
control, (by calling a blocking function that will switch to the
Hub), other greenlets won’t get a chance to run. This is
typically not an issue for an I/O bound app, but one should be aware
of this when doing something CPU intensive, or when calling blocking
I/O functions that bypass the libev event loop.
Even some apparently cooperative functions, like
gevent.sleep(), can temporarily take priority over
waiting I/O operations in some circumstances.
Synchronizing access to objects shared across the greenlets is
unnecessary in most cases (because yielding control is usually
explict), thus traditional synchronization devices like the
Semaphore classes, although present, aren’t used very
often. Other abstractions from threading and multiprocessing remain
useful in the cooperative world:
New greenlets are spawned by creating a
Greenlet instance and calling its
gevent.spawn() function is a shortcut that does exactly that). The
method schedules a switch to the greenlet that will happen as soon as the current greenlet gives up control.
If there is more than one active greenlet, they will be executed one
by one, in an undefined order as they each give up control to the
If there is an error during execution it won’t escape the greenlet’s boundaries. An unhandled error results in a stacktrace being printed, annotated by the failed function’s signature and arguments:
>>> gevent.spawn(lambda : 1/0) >>> gevent.sleep(1) Traceback (most recent call last): ... ZeroDivisionError: integer division or modulo by zero <Greenlet at 0x7f2ec3a4e490: <function <lambda...>> failed with ZeroDivisionError
The traceback is asynchronously printed to
sys.stderr when the greenlet dies.
Greenlet instances have a number of useful methods:
join– waits until the greenlet exits;
kill– interrupts greenlet’s execution;
get– returns the value returned by greenlet or re-raises the exception that killed it.
It is possible to customize the string printed after the traceback by subclassing the
and redefining its
To subclass a
gevent.Greenlet, override its
gevent.Greenlet._run() method and call
class MyNoopGreenlet(Greenlet): def __init__(self, seconds): Greenlet.__init__(self) self.seconds = seconds def _run(self): gevent.sleep(self.seconds) def __str__(self): return 'MyNoopGreenlet(%s)' % self.seconds
Greenlets can be killed synchronously from another greenlet. Killing will resume the sleeping greenlet, but instead
of continuing execution, a
GreenletExit will be raised.
>>> g = MyNoopGreenlet(4) >>> g.start() >>> g.kill() >>> g.dead True
gevent.greenlet.GreenletExit exception and its subclasses are handled differently than other exceptions.
GreenletExit is not considered an exceptional situation, so the traceback is not printed.
GreenletExit is returned by
get as if it were returned by the greenlet, not raised.
kill method can accept a custom exception to be raised:
>>> g = MyNoopGreenlet.spawn(5) # spawn() creates a Greenlet and starts it >>> g.kill(Exception("A time to kill")) Traceback (most recent call last): ... Exception: A time to kill MyNoopGreenlet(5) failed with Exception
kill can also accept a timeout
argument specifying the number of seconds to wait for the greenlet to
exit. Note that
kill cannot guarantee
that the target greenlet will not ignore the exception (i.e., it might
catch it), thus it’s a good idea always to pass a timeout to
kill (otherwise, the greenlet doing the
killing will remain blocked forever).
The exact timing at which an exception is raised within a
target greenlet as the result of
kill is not defined. See that function’s
documentation for more details.
Many functions in the gevent API are synchronous, blocking the current
greenlet until the operation is done. For example,
kill waits until the target greenlet is
dead before returning . Many of
those functions can be made asynchronous by passing the keyword argument
Furthermore, many of the synchronous functions accept a timeout
argument, which specifies a limit on how long the function can block
gevent.event.AsyncResult.get(), and many more).
SSLObject instances can also have a timeout, set by the
When these are not enough, the
Timeout class can be used to
add timeouts to arbitrary sections of (cooperative, yielding) code.
Gevent comes with TCP/SSL/HTTP/WSGI servers. See Implementing servers.
Next page: What’s new in gevent 1.1