Eventlet
Eventlet is a concurrent networking library for Python that uses coroutines (greenlets) and non-blocking I/O (epoll/libevent) to enable blocking-style programming in a highly scalable, asynchronous environment. As of version 0.41.0, Eventlet is in maintenance mode, discouraging new projects from using it and planning for its eventual retirement in favor of `asyncio` due to compatibility issues with newer Python versions and a growing gap in maintenance.
Common errors
-
RecursionError: maximum recursion depth exceeded
cause This error frequently occurs when `eventlet.monkey_patch()` is called too late in the application's execution, after other modules (especially those performing network I/O like `requests` or `ssl`) have already been imported, leading to conflicts in the patched functions and excessive recursion during operations, particularly with SSL.fixEnsure that `eventlet.monkey_patch()` is called as one of the very first actions in your application's main script, before any other modules that perform blocking I/O are imported. Updating `eventlet` and `dnspython` might also resolve it for some specific version combinations. -
RuntimeError: You need to use the eventlet server
cause This error typically arises when using Flask-SocketIO with Eventlet installed, but the Flask application is being run using the default Flask development server (`app.run()`) instead of the Eventlet-compatible server provided by Flask-SocketIO.fixTo use Eventlet as the asynchronous server for Flask-SocketIO, you must start your application using `socketio.run(app)` instead of `app.run()`. -
AttributeError: module 'ssl' has no attribute 'wrap_socket'
cause This issue occurs because Eventlet's monkey-patching mechanism attempts to access `ssl.wrap_socket()`, a function that was removed in Python 3.12. This indicates a fundamental incompatibility between Eventlet and newer Python versions.fixTo resolve this, you generally need to use a Python version older than 3.12. Given Eventlet's maintenance status, the recommended long-term solution is to migrate your project to a more actively maintained asynchronous framework like `asyncio` or `gevent`. -
DeprecationWarning: Eventlet is deprecated.
cause This warning signals that the Eventlet library is in maintenance mode, and its developers actively discourage its use for new projects due to ongoing compatibility challenges with newer Python versions and a lack of active maintenance.fixFor any new projects, it is strongly recommended to use modern asynchronous libraries such as `asyncio` (built into Python) or `gevent`. For existing projects using Eventlet, plan and execute a migration to one of these actively maintained alternatives.
Warnings
- deprecated Eventlet is officially in maintenance mode, and new usages are heavily discouraged. The project aims to plan its retirement due to compatibility challenges with modern Python and a shift towards `asyncio` as the preferred concurrency model.
- breaking Eventlet's monkey-patching mechanism struggles with recent Python versions (e.g., Python 3.12 and beyond), leading to internal functionalities not working correctly or causing unexpected behavior. This limits projects from adopting the latest Python improvements.
- gotcha Mixing Eventlet green threads with `asyncio`'s async functions has known limitations. Eventlet thread locals, `eventlet.greenthread.getcurrent()`, and Eventlet locks/queues may not work correctly when interacting directly between the two concurrency models in the same thread.
- gotcha Eventlet's green threads can lead to excessive memory consumption and inefficient resource management, especially under heavy loads or in large-scale applications, contributing to performance bottlenecks.
Install
-
pip install eventlet
Imports
- monkey_patch
import eventlet eventlet.monkey_patch()
- spawn
import threading threading.Thread(target=my_function).start()
import eventlet eventlet.spawn(my_function, arg1, arg2)
- sleep
import time time.sleep(0)
import eventlet eventlet.sleep(0)
Quickstart
import eventlet
from eventlet.green import urllib.request
import time
eventlet.monkey_patch()
def fetch_url(url):
print(f"Fetching {url}...")
try:
# urllib.request becomes non-blocking after monkey_patch()
response = urllib.request.urlopen(url)
data = response.read()
print(f"Finished fetching {url}, size: {len(data)} bytes")
except Exception as e:
print(f"Error fetching {url}: {e}")
if __name__ == '__main__':
urls = [
'http://www.google.com',
'http://www.bing.com',
'http://www.yahoo.com',
]
print("Starting concurrent fetches...")
pool = eventlet.GreenPool()
for url in urls:
pool.spawn(fetch_url, url)
pool.waitall()
print("All fetches complete.")
print("\nDemonstrating concurrent sleep:")
def greet(name, delay):
eventlet.sleep(delay) # Cooperative sleep
print(f"Hello, {name} after {delay} seconds!")
pool_sleep = eventlet.GreenPool()
pool_sleep.spawn(greet, "Alice", 2)
pool_sleep.spawn(greet, "Bob", 1)
pool_sleep.waitall()
print("All greetings complete.")