{"id":8295,"library":"loop-rate-limiters","title":"Loop Rate Limiters","description":"Loop-rate-limiters (current version 1.2.0) is a Python library providing simple frequency regulators for loops, offering an API similar to `rospy.Rate`. It supports both synchronous and asynchronous (asyncio) operations, ensuring code execution at a desired frequency. The library maintains an active development pace with regular patch and minor releases to introduce new features, fix bugs, and improve logging.","status":"active","version":"1.2.0","language":"en","source_language":"en","source_url":"https://github.com/stephane-caron/loop-rate-limiters","tags":["rate-limiting","asyncio","concurrency","timing","robotics"],"install":[{"cmd":"pip install loop-rate-limiters","lang":"bash","label":"PyPI"}],"dependencies":[],"imports":[{"symbol":"RateLimiter","correct":"from loop_rate_limiters import RateLimiter"},{"symbol":"AsyncRateLimiter","correct":"from loop_rate_limiters import AsyncRateLimiter"}],"quickstart":{"code":"import asyncio\nfrom loop_rate_limiters import AsyncRateLimiter\nimport os\n\nasync def main():\n    # Example with an asynchronous rate limiter\n    # Limits to 400 Hz (iterations per second)\n    rate = AsyncRateLimiter(frequency=400.0)\n    for i in range(10):\n        loop_time = asyncio.get_event_loop().time()\n        print(f\"Async loop iteration {i} at {loop_time:.3f} s\")\n        await rate.sleep()\n\n    print(\"\\nSynchronous example (not shown in quickstart, but available):\")\n    from time import perf_counter\n    from loop_rate_limiters import RateLimiter\n    sync_rate = RateLimiter(frequency=10.0) # 10 Hz\n    for i in range(5):\n        print(f\"Sync loop iteration {i} at {perf_counter():.3f} s\")\n        sync_rate.sleep()\n\nif __name__ == \"__main__\":\n    asyncio.run(main())","lang":"python","description":"This quickstart demonstrates the usage of `AsyncRateLimiter` to regulate the frequency of an asynchronous loop. A synchronous `RateLimiter` example is also included to show its basic usage."},"warnings":[{"fix":"Upgrade your Python environment to version 3.9 or higher.","message":"Python 3.8 support was removed in version 1.1.0. The library now requires Python 3.9 or newer.","severity":"breaking","affected_versions":">=1.1.0"},{"fix":"If your code relies on catching `RuntimeError` for `AsyncRateLimiter`'s loop status, update your error handling to check for warnings or ensure an `asyncio` loop is always active. Ensure you use `asyncio.run()` or a similar mechanism.","message":"In `AsyncRateLimiter`, previous versions (pre-1.1.0) would raise a `RuntimeError` if an `asyncio` event loop was not running. From v1.1.0 onwards, this behavior changed to issuing a warning instead of raising an exception.","severity":"breaking","affected_versions":">=1.1.0"},{"fix":"Do not attempt to modify attributes like `rate.period` or `rate.slack` directly after initialization. Instead, set them during the `RateLimiter` or `AsyncRateLimiter` constructor.","message":"Prior to version 0.3.0, attributes like `period` and `slack` on `RateLimiter` objects were writable. From version 0.3.0, these attributes became read-only properties.","severity":"breaking","affected_versions":">=0.3.0"},{"fix":"Upgrade to version 1.1.1 or newer to ensure lateness warnings report correct (positive) durations.","message":"Versions 1.1.0 had a bug where loop lateness was reported with a negative duration in warning messages. This was fixed in subsequent patch releases.","severity":"gotcha","affected_versions":"1.1.0"},{"fix":"Upgrade to version 1.2.0 or newer to benefit from the fix for the `AsyncRateLimiter` initialization bug.","message":"An initialization bug in `AsyncRateLimiter` was fixed in version 1.2.0. Users on older versions might experience unexpected behavior related to the limiter's internal state.","severity":"gotcha","affected_versions":"<1.2.0"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure your Python environment is 3.9 or newer (`python --version`). If it is, reinstall the package: `pip install --upgrade loop-rate-limiters`.","cause":"The library requires Python 3.9 or higher since version 1.1.0. This error might occur if you are running an older Python version or if the package is not installed correctly.","error":"ModuleNotFoundError: No module named 'loop_rate_limiters'"},{"fix":"Always run asynchronous code, including `AsyncRateLimiter`, within an `asyncio` event loop (e.g., by calling `asyncio.run(your_async_function())`). If on v1.1.0+, check logs for warnings instead of expecting an exception.","cause":"When using `AsyncRateLimiter` in versions prior to 1.1.0, this error would occur if the `AsyncRateLimiter` was instantiated or its `sleep()` method called without an active `asyncio` event loop. From v1.1.0, this became a warning instead of an error.","error":"RuntimeError: There is no current event loop in thread '...'"},{"fix":"These attributes can only be set during the object's initialization (e.g., `rate = RateLimiter(frequency=10.0)`). If you need to change the frequency, create a new `RateLimiter` instance.","cause":"From version 0.3.0 onwards, attributes like `period`, `slack`, and `next_tick` of `RateLimiter` and `AsyncRateLimiter` are read-only properties.","error":"AttributeError: can't set attribute 'period'"},{"fix":"Upgrade to `loop-rate-limiters` version 1.1.1 or higher to resolve this issue and get correctly signed lateness warnings.","cause":"This was a known bug in version 1.1.0 where the sign of the lateness duration was inverted in warning messages.","error":"Lateness warning shows a negative duration (e.g., 'Loop is late by -0.002 s')"}]}