0
# async-timeout
1
2
Timeout context manager for asyncio programs that provides a simple, efficient way to apply timeout logic around blocks of asynchronous code. This library offers an alternative to `asyncio.wait_for()` that doesn't create new tasks, supports rescheduling timeouts during execution, and provides methods to check if timeouts expired.
3
4
## Package Information
5
6
- **Package Name**: async-timeout
7
- **Package Type**: pypi
8
- **Language**: Python
9
- **Version**: 5.0.1
10
- **Installation**: `pip install async-timeout`
11
- **Python Requirements**: >=3.8
12
13
## Core Imports
14
15
```python
16
from async_timeout import timeout, timeout_at
17
```
18
19
Import the Timeout class for type hints:
20
21
```python
22
from async_timeout import timeout, timeout_at, Timeout
23
```
24
25
Complete public API (all available exports):
26
27
```python
28
from async_timeout import timeout, timeout_at, Timeout
29
# Available exports: timeout, timeout_at, Timeout
30
```
31
32
## Basic Usage
33
34
```python
35
from async_timeout import timeout
36
import asyncio
37
import aiohttp
38
39
async def main():
40
# Basic relative timeout
41
async with timeout(1.5):
42
await some_async_operation()
43
44
# Absolute timeout
45
loop = asyncio.get_running_loop()
46
async with timeout_at(loop.time() + 10):
47
await some_async_operation()
48
49
# Check if timeout occurred
50
async with timeout(2.0) as cm:
51
try:
52
await some_async_operation()
53
except asyncio.TimeoutError:
54
if cm.expired:
55
print("Operation timed out")
56
```
57
58
## Architecture
59
60
The async-timeout package provides dual implementations based on Python version:
61
62
- **Python 3.11+**: Inherits from `asyncio.Timeout` for full compatibility with the standard library
63
- **Older Python**: Standalone implementation with equivalent functionality and API
64
65
Both implementations provide the same public API surface and behavior, ensuring backward compatibility while taking advantage of built-in features when available.
66
67
## Capabilities
68
69
### Timeout Creation Functions
70
71
Functions for creating timeout context managers with relative or absolute timing.
72
73
```python { .api }
74
def timeout(delay: Optional[float]) -> Timeout:
75
"""
76
Create a timeout context manager with relative delay.
77
78
Args:
79
delay: Value in seconds or None to disable timeout logic
80
81
Returns:
82
Timeout context manager instance
83
"""
84
85
def timeout_at(deadline: Optional[float]) -> Timeout:
86
"""
87
Create a timeout context manager with absolute deadline.
88
89
Args:
90
deadline: Absolute time in loop.time() clock system or None
91
92
Returns:
93
Timeout context manager instance
94
"""
95
```
96
97
### Timeout Context Manager
98
99
The main context manager class that handles timeout logic and provides runtime control over timeouts.
100
101
```python { .api }
102
class Timeout:
103
"""
104
Timeout context manager for asyncio programs.
105
106
Use via async with statement for timeout functionality.
107
Provides methods for checking expiration and modifying timeouts during execution.
108
"""
109
110
@property
111
def expired(self) -> bool:
112
"""
113
Check if timeout expired during execution.
114
115
Note:
116
In Python 3.11+, this is also callable: expired() returns bool
117
118
Returns:
119
True if timeout occurred, False otherwise
120
"""
121
122
@property
123
def deadline(self) -> Optional[float]:
124
"""
125
Get the deadline time in loop.time() clock system.
126
127
Returns:
128
Float timestamp or None if no deadline set
129
"""
130
131
def reject(self) -> None:
132
"""
133
Cancel/reject scheduled timeout.
134
135
Disables the timeout while context manager is active.
136
"""
137
138
def shift(self, delay: float) -> None:
139
"""
140
Advance timeout by delay seconds (can be negative).
141
142
Args:
143
delay: Number of seconds to shift (positive or negative)
144
145
Raises:
146
RuntimeError: If deadline is not scheduled
147
"""
148
149
def update(self, deadline: float) -> None:
150
"""
151
Set absolute deadline value.
152
153
Args:
154
deadline: Absolute time in loop.time() clock system
155
156
Note:
157
If deadline is in past, timeout is raised immediately
158
"""
159
160
def when(self) -> Optional[float]:
161
"""
162
Get the scheduled deadline time (Python 3.11+ only).
163
164
Returns:
165
Float timestamp or None if no deadline set
166
167
Note:
168
This method is only available in Python 3.11+ as part of asyncio.Timeout compatibility
169
"""
170
171
def reschedule(self, deadline: Optional[float]) -> None:
172
"""
173
Reschedule the timeout to a new deadline (Python 3.11+ only).
174
175
Args:
176
deadline: New absolute deadline or None to cancel timeout
177
178
Note:
179
This method is only available in Python 3.11+ as part of asyncio.Timeout compatibility
180
"""
181
```
182
183
## Usage Examples
184
185
### Basic Timeout with HTTP Request
186
187
```python
188
import asyncio
189
import aiohttp
190
from async_timeout import timeout
191
192
async def fetch_with_timeout():
193
async with timeout(5.0):
194
async with aiohttp.ClientSession() as session:
195
async with session.get('https://example.com') as response:
196
return await response.text()
197
198
# Usage
199
try:
200
result = await fetch_with_timeout()
201
print("Request completed successfully")
202
except asyncio.TimeoutError:
203
print("Request timed out after 5 seconds")
204
```
205
206
### Timeout Management and Rescheduling
207
208
```python
209
import asyncio
210
from async_timeout import timeout
211
212
async def adaptive_timeout_example():
213
async with timeout(3.0) as cm:
214
# Start some operation
215
await asyncio.sleep(1)
216
217
# Check if we need more time and extend timeout
218
if some_condition:
219
cm.shift(2.0) # Add 2 more seconds
220
print(f"Extended deadline to: {cm.deadline}")
221
222
# Continue operation
223
await asyncio.sleep(2)
224
225
# Check if timeout occurred
226
if cm.expired:
227
print("Operation was cancelled due to timeout")
228
else:
229
print("Operation completed within timeout")
230
```
231
232
### Disabling Timeout Dynamically
233
234
```python
235
import asyncio
236
from async_timeout import timeout
237
238
async def conditional_timeout():
239
async with timeout(2.0) as cm:
240
# Start operation
241
await asyncio.sleep(0.5)
242
243
# Conditionally disable timeout
244
if fast_path_available:
245
cm.reject() # Remove timeout
246
await fast_operation()
247
else:
248
await slow_operation()
249
```
250
251
### Absolute Timeout Usage
252
253
```python
254
import asyncio
255
from async_timeout import timeout_at
256
257
async def scheduled_timeout():
258
loop = asyncio.get_running_loop()
259
start_time = loop.time()
260
261
# Set absolute deadline 10 seconds from now
262
async with timeout_at(start_time + 10) as cm:
263
await some_long_operation()
264
265
# Update to new absolute deadline if needed
266
if need_more_time:
267
cm.update(start_time + 15)
268
```
269
270
### Python 3.11+ Compatibility Methods
271
272
```python
273
import asyncio
274
import sys
275
from async_timeout import timeout
276
277
async def python311_features():
278
if sys.version_info >= (3, 11):
279
async with timeout(3.0) as cm:
280
# Use when() method to get deadline (Python 3.11+ only)
281
current_deadline = cm.when()
282
print(f"Current deadline: {current_deadline}")
283
284
# Use reschedule() method (Python 3.11+ only)
285
cm.reschedule(current_deadline + 2.0)
286
287
# expired can be called as method or accessed as property
288
if cm.expired(): # Method call
289
print("Timeout expired (method)")
290
if cm.expired: # Property access
291
print("Timeout expired (property)")
292
293
await some_operation()
294
```
295
296
## Error Handling
297
298
The package raises standard asyncio exceptions:
299
300
- **`asyncio.TimeoutError`**: Raised when timeout expires (converted from internal `CancelledError`)
301
- **`RuntimeError`**: Raised on invalid state operations (e.g., rescheduling after context exit)
302
303
```python
304
import asyncio
305
from async_timeout import timeout
306
307
async def error_handling_example():
308
try:
309
async with timeout(1.0) as cm:
310
await some_operation()
311
except asyncio.TimeoutError:
312
if cm.expired:
313
print("Operation timed out")
314
else:
315
print("TimeoutError from operation itself")
316
except RuntimeError as e:
317
print(f"Invalid timeout operation: {e}")
318
```
319
320
## Deprecation Notice
321
322
This library is deprecated in favor of the built-in `asyncio.timeout` available in Python 3.11+. However, it remains maintained for backward compatibility and provides identical functionality across Python versions.
323
324
For new code targeting Python 3.11+, consider using the conditional import pattern:
325
326
```python
327
import sys
328
329
if sys.version_info >= (3, 11):
330
from asyncio import timeout, timeout_at
331
else:
332
from async_timeout import timeout, timeout_at
333
```