Utility for handling rate limiting in a centralized manner
Project description
CentralizedRateLimiter
A robust, centralized rate limiting utility for Python applications that need precise control over API request rates with built-in retry mechanisms and support for multiple rate limits.
๐ง Installation
pip install centralized-rate-limiter
๐ Features
- Multiple Rate Limits: Support for multiple concurrent rate limits (e.g., per-second, per-minute, per-hour)
- Centralized Configuration: Set rate limiting parameters once and reuse across your application for all request methods
- Comprehensive Retry Logic: Built-in exponential backoff and configurable retry attempts
- Thread-Safe: Reliable rate limiting in multi-threaded environments
- Flexible HTTP Support: Works with all standard HTTP methods
- Session Management: Extends
requests.Sessionfor seamless integration - Type Hints: Full type annotation support for better IDE integration
๐ฏ Quick Start
from centralized_rate_limiter import get_rate_limiter
# Create a rate limiter with single rate limit (backward compatible)
rate_limiter = get_rate_limiter(
requests_per_second=10,
total_retries=5,
backoff_factor=0.25
)
# Create a rate limiter with multiple rate limits
rate_limiter = get_rate_limiter(
requests_per_second=10, # Base rate: 10 requests per second
additional_limits=[
(60, 60), # 60 requests per minute
(2000, 3600) # 2000 requests per hour
],
total_retries=5,
backoff_factor=0.25
)
# Use it for your API calls
response = rate_limiter.get('https://api.example.com/data')
# Works with all HTTP methods
post_response = rate_limiter.post(
'https://api.example.com/create',
json={'key': 'value'}
)
๐ง Advanced Usage
Custom Configuration
from centralized_rate_limiter import RateLimitedSession
# Create a session with multiple rate limits
session = RateLimitedSession(
requests_per_second=5,
additional_limits=[
(100, 60), # 100 requests per minute
(2000, 3600) # 2000 requests per hour
],
total_retries=3,
backoff_factor=0.5
)
# Use session in your application
responses = []
for endpoint in endpoints:
response = session.get(endpoint)
responses.append(response)
Error Handling
from requests.exceptions import RetryError
try:
response = rate_limiter.get('https://api.example.com/data')
data = response.json()
except RetryError:
print("Max retries exceeded")
except Exception as e:
print(f"An error occurred: {e}")
๐ Configuration Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
requests_per_second |
int | 10 | Maximum number of requests allowed per second |
additional_limits |
List[Tuple[int, float]] | None | Additional rate limits as (max_calls, period) tuples |
total_retries |
int | 5 | Maximum number of retry attempts for failed requests |
backoff_factor |
float | 0.25 | Multiplier for exponential backoff between retries |
Additional Limits Format
The additional_limits parameter accepts a list of tuples, where each tuple contains:
- First element: Maximum number of calls allowed in the period
- Second element: Period in seconds
Example:
additional_limits=[
(60, 60), # 60 calls per 60 seconds (per minute)
(2000, 3600) # 2000 calls per 3600 seconds (per hour)
]
๐ค When to Use This vs. Other Solutions
Use CentralizedRateLimiter When You Need:
-
Multiple Rate Limits
- You need to handle multiple concurrent rate limits (e.g., per-second, per-minute, per-hour)
- You want to enforce different rate limits for different time windows
- You need to comply with complex API rate limit requirements
-
Centralized Rate Limiting and Retry Logic
- You want a single solution that handles both rate limiting and retries
- You want a single rate limit for all your requests methods
- You need fine-grained control over retry behavior
-
Thread-Safe Operation
- Your application makes API calls from multiple threads
- You need reliable rate limiting in concurrent scenarios
-
Session Management
- You want to maintain session state across requests
- You need to reuse connections for better performance
Consider Alternatives When:
-
Distributed Rate Limiting Required
- Consider
python-redis-rate-limitfor distributed systems - Use
Flask-Limiterfor API endpoint protection
- Consider
-
Simpler Requirements
- Use
requests-ratelimiterfor basic rate limiting - Use
backoffpackage for simple retry logic
- Use
-
Async Operation
- Consider
aiohttpwithaiohttp-client-manager - Use
asynciobased solutions for async workflows
- Consider
๐ How It Works
The library uses a combination of:
- Thread-safe rate limiting for multiple concurrent limits
- Decorator-based rate limiting using the
ratelimitpackage urllib3.util.Retryfor configurable retry behavior- Custom session management extending
requests.Session
Example retry sequence:
Request 1 (fails) โ Wait 0.25s โ Retry 1 (fails) โ Wait 0.5s โ Retry 2 (succeeds)
Example with multiple rate limits:
# Configuration
limits = [
(60, 60), # 60 requests per minute
(2000, 3600) # 2000 requests per hour
]
# The rate limiter will ensure all limits are respected:
# - No more than 60 requests in any 60-second window
# - No more than 2000 requests in any 3600-second (1 hour) window
๐ ๏ธ Development
Prerequisites
- Python 3.7+
- Make (optional, but recommended)
- Git
Setting Up Development Environment
- Clone the repository:
git clone https://github.com/waddafunk/CentralizedRateLimiter.git
cd CentralizedRateLimiter
- Install development dependencies:
make dev-install
Or without make:
python -m pip install -e ".[dev]"
Development Tools
The project uses several development tools, all configured in pyproject.toml:
Code Formatting
- Black: Code formatter with a line length of 88 characters
- isort: Import statement organizer, configured to work with Black
- pyupgrade: Automatically upgrades Python syntax for newer versions
# Format all code
make format
or without make
# Individual tools
python -m black .
python -m isort .
python -m pyupgrade --py37-plus **/*.py
Code Quality
- pylint: Static code analysis
- flake8: Style guide enforcement
# Run all linters
make lint
or without make
python -m pylint centralized_rate_limiter tests
python -m flake8 centralized_rate_limiter tests
Testing
- pytest: Test framework
- pytest-cov: Coverage reporting
- responses: HTTP request mocking
# Run tests with coverage
make test
or without make
make coverage
Development Workflow
- Create a new branch for your feature:
git checkout -b feature/your-feature-name
- Make your changes and ensure quality:
make format # Format code
make lint # Check code quality
make test # Run tests
# Or run all checks at once:
make all
- Build and check the package:
make build
- Submit a pull request
Available Make Commands
| Command | Description |
|---|---|
make install |
Install package for production |
make dev-install |
Install package with development dependencies |
make format |
Format code using black and isort |
make lint |
Run code quality checks |
make test |
Run tests with pytest |
make coverage |
Generate test coverage report |
make clean |
Remove build artifacts and cache files |
make build |
Build distribution packages |
make publish |
Prepare package for PyPI publishing |
make all |
Run all quality checks and tests |
make help |
Show available commands |
Project Structure
centralized_rate_limiter/
โโโ .git/
โโโ .gitignore
โโโ centralized_rate_limiter/
โ โโโ __init__.py
โ โโโ rate_limiting.py
โโโ tests/
โ โโโ test_rate_limiting.py
โโโ Makefile
โโโ pyproject.toml
โโโ README.md
โโโ LICENSE
Configuration Files
pyproject.toml
The pyproject.toml file contains all project configurations:
- Build system configuration
- Package metadata
- Dependencies (both runtime and development)
- Tool configurations:
- pytest settings
- coverage settings
- black configuration
- isort configuration
Makefile
The Makefile provides convenient commands for common development tasks. See the commands table above for available operations.
Continuous Integration
The project uses GitHub Actions for CI/CD, running the following checks on each pull request:
- Code formatting (black, isort)
- Linting (pylint, flake8)
- Tests with coverage reporting
- Package building
๐ค Contributing
Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
๐ License
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
๐ API Reference
RateLimitedSession
class RateLimitedSession(requests.Session):
"""A rate-limited HTTP session with built-in retry logic."""
def __init__(
self,
requests_per_second: int = 10,
total_retries: int = 5,
backoff_factor: float = 0.25,
additional_limits: Optional[List[Tuple[int, float]]] = None
) -> None:
"""Initialize a new rate-limited session."""
get_rate_limiter
def get_rate_limiter(
requests_per_second: int = 10,
total_retries: int = 5,
backoff_factor: float = 0.25,
additional_limits: Optional[List[Tuple[int, float]]] = None
) -> RateLimitedSession:
"""Create a new rate-limited session with specified parameters."""
๐ Acknowledgments
๐ง Contact
For questions and support, please open an issue in the GitHub repository.
Made with โค๏ธ for the Python community
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 centralized_rate_limiter-0.2.2.tar.gz.
File metadata
- Download URL: centralized_rate_limiter-0.2.2.tar.gz
- Upload date:
- Size: 13.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.21
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff3b267ba0641a0e3b60cf77fb6734c0ee0c504f0aa3fbf005352da3cf7423c4
|
|
| MD5 |
5ae318cb2d2205a4adf36102ce64f64f
|
|
| BLAKE2b-256 |
d42409452b955b5e458ba13b9abe318837d9be092cd19ef0577b72e32d6eea8e
|
File details
Details for the file centralized_rate_limiter-0.2.2-py3-none-any.whl.
File metadata
- Download URL: centralized_rate_limiter-0.2.2-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.21
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a75f8ddeec6e1b3f0403874258dadefb1b26e5d60f61e4c9416293b6df1c6da
|
|
| MD5 |
60f706b0556d634d96bf3e5aad133593
|
|
| BLAKE2b-256 |
03b69ca7cd2559523055dce38205a44d7efbece4475e821590e344d90d4894bb
|