Eventlet is thread-safe and can be used in conjunction with normal Python threads. The way this works is that coroutines are confined to their ‘parent’ Python thread. It’s like each thread contains its own little world of coroutines that can switch between themselves but not between coroutines in other threads.
You can only communicate cross-thread using the “real” thread primitives and pipes. Fortunately, there’s little reason to use threads for concurrency when you’re already using coroutines.
The vast majority of the times you’ll want to use threads are to wrap some operation that is not “green”, such as a C library that uses its own OS calls to do socket operations. The
tpool module is provided to make these uses simpler.
The optional pyevent hub is not compatible with threads.
Tpool - Simple thread pool¶
>>> import thread >>> from eventlet import tpool >>> def my_func(starting_ident): ... print("running in new thread:", starting_ident != thread.get_ident()) ... >>> tpool.execute(my_func, thread.get_ident()) running in new thread: True
By default there are 20 threads in the pool, but you can configure this by setting the environment variable
EVENTLET_THREADPOOL_SIZE to the desired pool size before importing tpool.
execute(meth, *args, **kwargs)¶
Execute meth in a Python thread, blocking the current coroutine/ greenthread until the method completes.
The primary use case for this is to wrap an object or module that is not amenable to monkeypatching or any of the other tricks that Eventlet uses to achieve cooperative yielding. With tpool, you can force such objects to cooperate with green threads by sticking them in native threads, at the cost of some overhead.
Proxy(obj, autowrap=(), autowrap_names=())¶
a simple proxy-wrapper of any object that comes with a methods-only interface, in order to forward every method invocation onto a thread in the native-thread pool. A key restriction is that the object’s methods should not switch greenlets or use Eventlet primitives, since they are in a different thread from the main hub, and therefore might behave unexpectedly. This is for running native-threaded code only.
It’s common to want to have some of the attributes or return values also wrapped in Proxy objects (for example, database connection objects produce cursor objects which also should be wrapped in Proxy objects to remain nonblocking). autowrap, if supplied, is a collection of types; if an attribute or return value matches one of those types (via isinstance), it will be wrapped in a Proxy. autowrap_names is a collection of strings, which represent the names of attributes that should be wrapped in Proxy objects when accessed.