An asyncio-based rate limiter for API requests
Project description
Async Dual Rate Limiter
A production-ready asyncio-based rate limiter for Python that enforces both concurrent and time-based rate limits.
Features
- Enforce maximum concurrent requests
- Enforce maximum requests per time period
- Works as a context manager, decorator, or with explicit acquire/release
- Comprehensive metrics collection
- Production-ready error handling
- Task cancellation support
Installation
# Install from PyPI
pip install async-limiter
Or install from source:
# Clone the repository
git clone https://github.com/Shehryar718/async-limiter.git
cd async-limiter
# Install in development mode
pip install -e .
# Install with test dependencies
pip install -e ".[test]"
Usage
Basic Usage
import asyncio
from async_limiter import DualRateLimiter
# Create a rate limiter with max 5 concurrent requests and max 100 requests per minute
limiter = DualRateLimiter(max_concurrent=5, max_requests=100, time_period=60)
# Use as a context manager
async def fetch_data():
async with limiter:
# Your API call here
return await api_call()
# Or use acquire/release manually
async def fetch_data_manual():
await limiter.acquire()
try:
# Your API call here
return await api_call()
finally:
limiter.release()
# Or use as a decorator
@limiter.limit()
async def fetch_data_decorated():
# Your API call here
return await api_call()
With API Client Example
import asyncio
from aiohttp import ClientSession
from async_limiter import DualRateLimiter
class ApiClient:
def __init__(self, base_url="https://api.example.com"):
self.base_url = base_url
# Create a rate limiter for this API
self.rate_limiter = DualRateLimiter(
max_concurrent=5,
max_requests=10,
time_period=60,
name="example_api"
)
async def get_data(self, path, params=None):
"""Make a rate-limited GET request."""
url = f"{self.base_url}/{path}"
# Use the rate limiter as a context manager
async with self.rate_limiter:
async with ClientSession() as session:
response = await session.get(url, params=params)
data = await response.json()
return data
@property
def metrics(self):
"""Get rate limiter metrics."""
return self.rate_limiter.get_metrics()
# Usage
async def main():
api = ApiClient()
# Make multiple concurrent requests (will be automatically rate limited)
tasks = [api.get_data(f"resource/{i}") for i in range(20)]
results = await asyncio.gather(*tasks)
# Check metrics
print(api.metrics)
if __name__ == "__main__":
asyncio.run(main())
Metrics
Get detailed metrics from the rate limiter:
metrics = limiter.get_metrics()
print(metrics)
Example output:
{
"total_requests": 100,
"current_requests": 2,
"rate_limit_delays": 5,
"total_delay_time": 12.5,
"errors": 0,
"current_queue_size": 3,
"max_concurrent": 5,
"max_requests_per_period": 9,
"time_period": 60
}
Running Tests
The package includes comprehensive tests. To run them:
# Install test dependencies
pip install -e ".[test]"
# Run all tests
pytest
# Run specific test file
pytest tests/test_async_limiter.py
# Run tests with detailed output
pytest -v
# Run tests with log output
pytest -v --log-cli-level=INFO
# Run tests with coverage report
pytest --cov=async_limiter
Development
This project uses modern Python packaging with pyproject.toml. The development tools configured include:
- pytest: For running tests
- ruff: For code formatting and linting
- mypy: For type checking
- coverage: For measuring test coverage
Why Use Async Dual Rate Limiter?
Many APIs impose both concurrent and time-based rate limits. This package provides a clean, efficient solution to handle both types of limits with minimal overhead and maximum flexibility.
Key advantages:
- Production Ready: Thoroughly tested with extensive error handling
- Flexible API: Use as a context manager, decorator, or with explicit calls
- Detailed Metrics: Track usage and performance with built-in metrics
- Type Annotated: Full type annotations make integration easier
- Pure Python: No external dependencies required
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file async_limiter-1.1.0.tar.gz.
File metadata
- Download URL: async_limiter-1.1.0.tar.gz
- Upload date:
- Size: 10.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd9b84a36d745fa5622556f1423d04aa47ba9677f54892860b3f249c7f1f89b8
|
|
| MD5 |
79ca1cbef3a6058d7d07a78edf5f0a2a
|
|
| BLAKE2b-256 |
8d09588c439cc33a2ce5edf8576ef6efe7f5a7a8954aaa25fe78133ec9c202b8
|
File details
Details for the file async_limiter-1.1.0-py3-none-any.whl.
File metadata
- Download URL: async_limiter-1.1.0-py3-none-any.whl
- Upload date:
- Size: 7.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1eebc1d65372d5c65248afcbbf19725798f4b89eb56f845f42419cc06e37f7a2
|
|
| MD5 |
aaf9b30d9f49fd88a0e9a3e047626ff1
|
|
| BLAKE2b-256 |
4de325945907d7bae00b2ad884a832b2cf296e31f0e82f25d1ebf9d045253e63
|