{"id":1490,"library":"geventhttpclient","title":"geventhttpclient","description":"geventhttpclient is an asynchronous HTTP client library specifically designed to work with gevent, providing non-blocking HTTP requests. It is currently at version 2.3.9 and has a moderate release cadence, with updates typically several times a year as needed for bug fixes and compatibility.","status":"active","version":"2.3.9","language":"en","source_language":"en","source_url":"https://github.com/gevent/geventhttpclient","tags":["http","client","gevent","asynchronous","networking","greenlets"],"install":[{"cmd":"pip install geventhttpclient","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core dependency for asynchronous operations.","package":"gevent","optional":false},{"reason":"Optional for advanced SSL/TLS features.","package":"pyopenssl","optional":true},{"reason":"Optional for advanced SSL/TLS features (legacy Python 2 compatibility, often paired with pyopenssl).","package":"ndg-httpsclient","optional":true},{"reason":"Optional for advanced SSL/TLS features (often used by ndg-httpsclient).","package":"pyasn1","optional":true}],"imports":[{"symbol":"HTTPClient","correct":"from geventhttpclient import HTTPClient"},{"symbol":"HTTPClientPool","correct":"from geventhttpclient.pool import HTTPClientPool"},{"symbol":"response","correct":"from geventhttpclient import response"}],"quickstart":{"code":"import gevent\nfrom geventhttpclient import HTTPClient\nfrom gevent import monkey\nimport logging\n\n# Crucial for gevent to work properly\nmonkey.patch_all()\n\n# Optional: Set up basic logging to see gevent events if needed\n# logging.basicConfig(level=logging.INFO)\n\ndef fetch_url(url):\n    # Create a client instance for a specific host\n    # Using httpbin.org for a public, testable endpoint\n    client = HTTPClient.from_url(url, \n                                 connection_timeout=5, \n                                 network_timeout=10)\n    try:\n        # Make a GET request to a path relative to the client's base URL\n        resp = client.get('/get?foo=bar')\n        \n        print(f\"Requested: {url}/get?foo=bar\")\n        print(f\"Status: {resp.status}\")\n        print(f\"Headers: {resp.headers['Content-Type']}\")\n        \n        # Read the response body. For large responses, consider resp.read(chunk_size)\n        body = resp.read()\n        print(f\"Body snippet: {body[:100]}...\")\n\n    except Exception as e:\n        print(f\"Error fetching {url}: {e}\")\n    finally:\n        # Always close the client to release resources, especially connection pool\n        client.close()\n\nif __name__ == '__main__':\n    # Spawn a greenlet to run the network operation non-blocking\n    greenlet = gevent.spawn(fetch_url, 'http://httpbin.org')\n    # Wait for the greenlet to complete\n    greenlet.join()\n","lang":"python","description":"This quickstart demonstrates how to initialize gevent's monkey patching, create an `HTTPClient` instance, perform a GET request, and handle the response. It highlights the importance of `monkey.patch_all()` and proper client closure."},"warnings":[{"fix":"Ensure `from gevent import monkey; monkey.patch_all()` is called at the very beginning of your application's lifecycle, before any blocking I/O is performed.","message":"gevent's `monkey.patch_all()` is essential. If not called, `geventhttpclient` will perform blocking I/O operations, defeating the purpose of gevent.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Surround client usage with a `try...finally` block calling `client.close()` or use a `with` statement: `with HTTPClient.from_url(...) as client: ...`","message":"Always close `HTTPClient` instances explicitly (`client.close()`) or use them as context managers (`with HTTPClient(...) as client:`). Failing to do so can lead to connection leaks and resource exhaustion, especially when using connection pooling.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Check `response.status` after every request: `if not 200 <= response.status < 300: # handle error`. Alternatively, set `raise_request_exception=True` when initializing the client or on the request call: `client.get('/path', raise_request_exception=True)`.","message":"By default, `geventhttpclient` does not raise exceptions for HTTP error status codes (e.g., 4xx, 5xx). You must explicitly check `response.status` or configure the client to raise exceptions.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For large responses, read the body in chunks using `response.read(chunk_size)` or iterate over the response object if it supports chunked reading to process data incrementally.","message":"Reading the entire response body with `response.read()` loads it into memory. For very large responses, this can consume significant memory.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}