{"id":6373,"library":"grequests","title":"GRequests: Asynchronous HTTP Requests with Gevent","description":"grequests is a Python library that combines the popular `requests` library with `gevent` to enable easy asynchronous HTTP requests. It allows developers to send multiple HTTP requests concurrently, significantly reducing the time spent waiting for network I/O, particularly useful for tasks like web scraping and interacting with multiple API endpoints. The library's current version is 0.7.0, and while its release cadence is not strictly regular, it receives updates for compatibility and new features.","status":"active","version":"0.7.0","language":"en","source_language":"en","source_url":"https://github.com/spyoungtech/grequests","tags":["http","requests","gevent","async","concurrent","networking","web scraping"],"install":[{"cmd":"pip install grequests","lang":"bash","label":"Install with pip"}],"dependencies":[{"reason":"Core HTTP client functionality that grequests extends.","package":"requests","optional":false},{"reason":"Provides the coroutine-based concurrency model (greenlets) for asynchronous operations.","package":"gevent","optional":false}],"imports":[{"note":"Due to gevent's monkey-patching, `grequests` (which imports `gevent`) should generally be imported before other networking libraries like `requests` to ensure proper asynchronous behavior.","wrong":"import requests; import grequests","symbol":"grequests","correct":"import grequests"},{"note":"Used to send a collection of Request objects concurrently and retrieve responses.","symbol":"grequests.map","correct":"responses = grequests.map(requests_list)"},{"note":"Returns a generator of responses, which can offer performance gains. Responses are not guaranteed to be in the order of the original requests.","symbol":"grequests.imap","correct":"for response in grequests.imap(requests_list):"},{"note":"Returns a generator yielding (index, response) tuples. Unlike `imap`, it yields `None` for failed requests. Introduced in v0.7.0.","symbol":"grequests.imap_enumerated","correct":"for index, response in grequests.imap_enumerated(requests_list):"}],"quickstart":{"code":"import grequests\nimport time\n\nurls = [\n    'http://httpbin.org/delay/1',\n    'http://httpbin.org/status/200',\n    'http://httpbin.org/delay/3',\n    'http://httpbin.org/status/500'\n]\n\ndef exception_handler(request, exception):\n    print(f\"Request to {request.url} failed: {exception}\")\n\nstart_time = time.time()\n\n# Create a list of unsent Request objects\nreqs = (\n    grequests.get(u, timeout=2) for u in urls\n)\n\n# Send all requests concurrently using map\n# Responses will be in the same order as requests, with None for failed ones\nresponses = grequests.map(reqs, exception_handler=exception_handler, size=5)\n\nprint(f\"\\n--- Responses (using map, took {time.time() - start_time:.2f}s) ---\")\nfor response in responses:\n    if response:\n        print(f\"URL: {response.url}, Status: {response.status_code}\")\n    else:\n        print(\"Request failed or timed out.\")\n\nprint(\"\\n--- Responses (using imap_enumerated) ---\")\n# imap_enumerated yields (index, response) and includes Nones for failures\nreqs_for_imap_enumerated = (\n    grequests.get(u, timeout=2) for u in urls\n)\nfor index, response in grequests.imap_enumerated(reqs_for_imap_enumerated, exception_handler=exception_handler, size=5):\n    if response:\n        print(f\"Index: {index}, URL: {response.url}, Status: {response.status_code}\")\n    else:\n        print(f\"Index: {index}, Request failed or timed out.\")","lang":"python","description":"This quickstart demonstrates how to use `grequests.map` and `grequests.imap_enumerated` to send multiple GET requests concurrently. It includes a custom exception handler and sets a timeout for individual requests. `grequests.map` returns a list of responses (or `None` for failed requests) in the order of the initial requests, while `grequests.imap_enumerated` yields (index, response) tuples as responses become available, not necessarily in the original request order."},"warnings":[{"fix":"Ensure `import grequests` is placed at the very beginning of your script or module, before any other imports that perform I/O operations.","message":"Import `grequests` (and thus `gevent`) before `requests` or other networking libraries that might conflict with `gevent`'s monkey-patching. Incorrect import order can lead to unexpected blocking behavior or errors.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Iterate through the results and check if each `response` object is `None` before attempting to access its attributes (e.g., `if response: print(response.status_code)`). Consider using an `exception_handler` with `grequests.map` for more granular error reporting.","message":"When using `grequests.map()`, failed requests (e.g., due to timeouts or connection errors) will result in `None` being present in the returned list of responses. You must explicitly handle these `None` values.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If response order is critical, use `grequests.map()`. If processing responses as they arrive is sufficient and order is not important, `grequests.imap()` can be more performant. If you need the original index with `imap`-like behavior, use `grequests.imap_enumerated` (v0.7.0+), but note its `None` handling.","message":"`grequests.imap()` returns a generator of responses, and the order in which responses are yielded is arbitrary; it does not correspond to the order of the input requests. This differs from `grequests.map()` which maintains order.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use the `size` parameter in `grequests.map()` or `grequests.imap()` to limit the number of concurrent requests being made (e.g., `grequests.map(reqs, size=10)`). Adjust this value based on your system's capabilities and the target server's limitations.","message":"Making a large number of concurrent requests without controlling the pool size (`size` parameter) can lead to 'Too many open files' errors, rate limiting by target servers, or servers closing connections prematurely.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Review code using `grequests.imap` and test its behavior against version 0.4.0 or later to ensure it functions as expected. Refer to GitHub issue #111 if possible for specifics.","message":"The behavior of `grequests.imap` changed in version 0.4.0. While not explicitly detailed as a breaking change in releases, 'behavior changes' suggest that code relying on previous `imap` functionality might need adjustments.","severity":"breaking","affected_versions":"0.4.0 and later"},{"fix":"Upgrade to Python 3.7+ and ensure your `gevent` installation is compatible with your Python version. Consult `gevent`'s documentation for its specific Python compatibility matrix.","message":"The underlying `gevent` library has deprecated and removed support for older Python versions (e.g., Python 2.7, 3.6, and soon 3.9). While `grequests` itself doesn't always specify Python requirements, its compatibility is bound by `gevent`'s support.","severity":"deprecated","affected_versions":"May affect users on older Python environments, especially with newer `grequests`/`gevent` versions."}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z"}