0
# Ratelimit
1
2
A Python decorator library for implementing API rate limiting functionality that prevents functions from being called more frequently than specified limits. It provides a clean, decorator-based approach to enforce rate limits on function calls, helping developers avoid hitting API rate limits that could result in service bans.
3
4
## Package Information
5
6
- **Package Name**: ratelimit
7
- **Package Type**: pypi
8
- **Language**: Python
9
- **Version**: 2.2.1
10
- **Installation**: `pip install ratelimit`
11
12
## Core Imports
13
14
```python
15
from ratelimit import limits, RateLimitException, sleep_and_retry
16
```
17
18
Alternative imports:
19
20
```python
21
# Using backwards-compatible alias
22
from ratelimit import rate_limited, RateLimitException, sleep_and_retry
23
24
# Package-level import
25
import ratelimit
26
# Access via: ratelimit.limits, ratelimit.RateLimitException, etc.
27
```
28
29
## Basic Usage
30
31
```python
32
from ratelimit import limits, RateLimitException, sleep_and_retry
33
import requests
34
35
# Basic rate limiting
36
FIFTEEN_MINUTES = 900
37
38
@limits(calls=15, period=FIFTEEN_MINUTES)
39
def call_api(url):
40
response = requests.get(url)
41
if response.status_code != 200:
42
raise Exception('API response: {}'.format(response.status_code))
43
return response
44
45
# With exception handling
46
try:
47
result = call_api('https://api.example.com/data')
48
except RateLimitException as e:
49
print(f"Rate limit exceeded. Wait {e.period_remaining} seconds")
50
51
# Automatic retry on rate limit
52
@sleep_and_retry
53
@limits(calls=15, period=FIFTEEN_MINUTES)
54
def call_api_with_retry(url):
55
response = requests.get(url)
56
if response.status_code != 200:
57
raise Exception('API response: {}'.format(response.status_code))
58
return response
59
```
60
61
## Capabilities
62
63
### Rate Limiting Decorator
64
65
Prevents functions from being called more frequently than specified limits. The main decorator that enforces rate limits on function calls.
66
67
```python { .api }
68
class RateLimitDecorator(object):
69
def __init__(self, calls=15, period=900, clock=now, raise_on_limit=True):
70
"""
71
Rate limit decorator class. Available as 'limits' and 'rate_limited' aliases.
72
73
Parameters:
74
- calls (int): Maximum function invocations allowed within time period. Must be >= 1. Default: 15
75
- period (float): Time period in seconds before rate limit resets. Must be > 0. Default: 900 (15 minutes)
76
- clock (callable): Function returning current time as float. Default: time.monotonic or time.time
77
- raise_on_limit (bool): Whether to raise RateLimitException when limit exceeded. Default: True
78
"""
79
80
# Main alias (recommended)
81
limits = RateLimitDecorator
82
83
# Backwards compatibility alias
84
rate_limited = RateLimitDecorator
85
```
86
87
### Automatic Retry Decorator
88
89
Wraps rate-limited functions to automatically sleep and retry when rate limits are exceeded, ensuring every function call eventually succeeds.
90
91
```python { .api }
92
def sleep_and_retry(func):
93
"""
94
Decorator that rescues rate limit exceptions by sleeping until the rate limit resets.
95
96
Parameters:
97
- func (callable): The function to decorate
98
99
Returns:
100
- callable: Decorated function that automatically retries on rate limit
101
"""
102
```
103
104
### Rate Limit Exception
105
106
Custom exception raised when the number of function invocations exceeds the imposed rate limit. Contains information about the remaining time until the rate limit resets.
107
108
```python { .api }
109
class RateLimitException(Exception):
110
def __init__(self, message, period_remaining):
111
"""
112
Exception raised when rate limits are exceeded.
113
114
Parameters:
115
- message (str): Exception message
116
- period_remaining (float): Time remaining until rate limit resets
117
118
Attributes:
119
- period_remaining (float): Time in seconds until rate limit resets
120
"""
121
```
122
123
### Package Version
124
125
Package version constant.
126
127
```python { .api }
128
__version__ = "2.2.1"
129
```
130
131
## Implementation Details
132
133
```python { .api }
134
# Internal clock function used by the library (not exported)
135
# Uses monotonic time if available, otherwise falls back to system clock
136
now = time.monotonic if hasattr(time, 'monotonic') else time.time
137
```
138
139
## Usage Examples
140
141
### Custom Clock for Testing
142
143
```python
144
from ratelimit import limits
145
import time
146
147
class TestClock:
148
def __init__(self):
149
self.time = 0
150
151
def __call__(self):
152
return self.time
153
154
def advance(self, seconds):
155
self.time += seconds
156
157
clock = TestClock()
158
159
@limits(calls=2, period=10, clock=clock)
160
def test_function():
161
return "success"
162
163
# Function can be called twice
164
test_function() # Success
165
test_function() # Success
166
167
# Third call raises exception
168
try:
169
test_function() # RateLimitException
170
except RateLimitException:
171
print("Rate limit exceeded")
172
173
# Advance clock and try again
174
clock.advance(10)
175
test_function() # Success again
176
```
177
178
### Non-Exception Mode
179
180
```python
181
from ratelimit import limits
182
183
@limits(calls=1, period=60, raise_on_limit=False)
184
def api_call():
185
print("API called")
186
return "data"
187
188
# First call succeeds
189
result = api_call() # Prints "API called", returns "data"
190
191
# Second call silently skips execution
192
result = api_call() # Returns None, no print statement
193
```
194
195
### Integration with Exponential Backoff
196
197
```python
198
from ratelimit import limits, RateLimitException, sleep_and_retry
199
from backoff import on_exception, expo
200
201
@on_exception(expo, RateLimitException, max_tries=8)
202
@limits(calls=15, period=900)
203
def api_call_with_backoff(url):
204
# Your API call implementation
205
pass
206
207
# Alternative using sleep_and_retry (simpler but less flexible)
208
@sleep_and_retry
209
@limits(calls=15, period=900)
210
def api_call_simple_retry(url):
211
# Your API call implementation
212
pass
213
```
214
215
## Thread Safety
216
217
All decorators are thread-safe using `threading.RLock()`. Each decorated function maintains its own independent rate limit state, allowing multiple rate-limited functions to operate concurrently without interference.
218
219
## Error Handling
220
221
The package raises `RateLimitException` when rate limits are exceeded (unless `raise_on_limit=False`). This exception contains:
222
223
- Standard exception message
224
- `period_remaining` attribute: float indicating seconds until rate limit resets
225
226
Common error handling patterns:
227
228
```python
229
import time
230
from ratelimit import limits, RateLimitException
231
232
@limits(calls=1, period=60)
233
def rate_limited_function():
234
return "success"
235
236
# Manual retry with exponential backoff
237
max_retries = 3
238
for attempt in range(max_retries):
239
try:
240
result = rate_limited_function()
241
break
242
except RateLimitException as e:
243
if attempt == max_retries - 1:
244
raise
245
wait_time = min(e.period_remaining * (2 ** attempt), 300) # Cap at 5 minutes
246
time.sleep(wait_time)
247
```