0
# Timeouts
1
2
Timeout management and control flow utilities including context managers for timeouts and cooperative equivalents of standard library functions. Timeouts in gevent work cooperatively with the event loop.
3
4
## Capabilities
5
6
### Timeout Class
7
8
Context manager and object for managing timeouts.
9
10
```python { .api }
11
class Timeout:
12
"""
13
Timeout context manager and exception for cooperative timeout handling.
14
"""
15
16
def __init__(self, seconds=None, exception=None, ref=True, priority=-1):
17
"""
18
Create a timeout.
19
20
Parameters:
21
- seconds: float, timeout duration in seconds (None for no timeout)
22
- exception: exception to raise on timeout (Timeout by default)
23
- ref: bool, whether timeout should keep event loop alive
24
- priority: int, priority for timeout callback
25
"""
26
27
def start(self):
28
"""
29
Start the timeout timer.
30
31
Returns:
32
None
33
"""
34
35
def cancel(self):
36
"""
37
Cancel the timeout.
38
39
Returns:
40
None
41
"""
42
43
def close(self):
44
"""
45
Close and cleanup timeout.
46
47
Returns:
48
None
49
"""
50
51
@property
52
def pending(self) -> bool:
53
"""Whether timeout is active and pending."""
54
55
@property
56
def seconds(self) -> float:
57
"""Timeout duration in seconds."""
58
59
def __enter__(self):
60
"""
61
Enter timeout context.
62
63
Returns:
64
self
65
"""
66
67
def __exit__(self, exc_type, exc_val, exc_tb):
68
"""
69
Exit timeout context and cleanup.
70
71
Parameters:
72
- exc_type: exception type
73
- exc_val: exception value
74
- exc_tb: exception traceback
75
76
Returns:
77
None
78
"""
79
```
80
81
### Timeout Functions
82
83
Utility functions for timeout operations.
84
85
```python { .api }
86
def with_timeout(seconds, function, *args, **kwargs) -> any:
87
"""
88
Run function with timeout.
89
90
Parameters:
91
- seconds: float, timeout in seconds
92
- function: callable to execute
93
- *args: positional arguments for function
94
- **kwargs: keyword arguments for function
95
96
Returns:
97
Function result
98
99
Raises:
100
Timeout: if function doesn't complete within timeout
101
"""
102
```
103
104
## Usage Examples
105
106
### Basic Timeout Usage
107
108
```python
109
import gevent
110
from gevent import timeout
111
112
def slow_function():
113
print("Starting slow operation...")
114
gevent.sleep(5) # Simulate 5-second operation
115
print("Slow operation completed!")
116
return "Success"
117
118
# Using timeout as context manager
119
try:
120
with timeout.Timeout(2): # 2-second timeout
121
result = slow_function()
122
print(f"Result: {result}")
123
except timeout.Timeout:
124
print("Operation timed out!")
125
```
126
127
### Custom Timeout Exception
128
129
```python
130
import gevent
131
from gevent import timeout
132
133
class CustomTimeoutError(Exception):
134
pass
135
136
def risky_operation():
137
gevent.sleep(3)
138
return "Completed"
139
140
try:
141
with timeout.Timeout(1, CustomTimeoutError("Custom timeout message")):
142
result = risky_operation()
143
print(result)
144
except CustomTimeoutError as e:
145
print(f"Custom timeout: {e}")
146
```
147
148
### Using with_timeout Function
149
150
```python
151
import gevent
152
from gevent import timeout
153
154
def network_operation():
155
# Simulate network operation
156
gevent.sleep(2)
157
return "Network data received"
158
159
def fallback_operation():
160
return "Fallback data"
161
162
# Try network operation with timeout, use fallback if it times out
163
try:
164
result = timeout.with_timeout(1, network_operation)
165
print(f"Success: {result}")
166
except timeout.Timeout:
167
print("Network operation timed out, using fallback")
168
result = fallback_operation()
169
print(f"Fallback: {result}")
170
```
171
172
### Multiple Operations with Different Timeouts
173
174
```python
175
import gevent
176
from gevent import timeout
177
178
def quick_task():
179
gevent.sleep(0.5)
180
return "Quick task done"
181
182
def medium_task():
183
gevent.sleep(2)
184
return "Medium task done"
185
186
def slow_task():
187
gevent.sleep(5)
188
return "Slow task done"
189
190
tasks = [
191
(quick_task, 1, "Quick"),
192
(medium_task, 3, "Medium"),
193
(slow_task, 4, "Slow")
194
]
195
196
results = []
197
for task_func, task_timeout, task_name in tasks:
198
try:
199
result = timeout.with_timeout(task_timeout, task_func)
200
results.append((task_name, result))
201
print(f"{task_name}: {result}")
202
except timeout.Timeout:
203
results.append((task_name, "TIMEOUT"))
204
print(f"{task_name}: Timed out")
205
206
print(f"\nFinal results: {results}")
207
```
208
209
### Timeout with Cleanup
210
211
```python
212
import gevent
213
from gevent import timeout
214
215
class Resource:
216
def __init__(self, name):
217
self.name = name
218
self.is_open = False
219
220
def open(self):
221
print(f"Opening resource {self.name}")
222
self.is_open = True
223
gevent.sleep(0.1) # Simulate opening time
224
225
def work(self):
226
if not self.is_open:
227
raise RuntimeError("Resource not open")
228
print(f"Working with resource {self.name}")
229
gevent.sleep(3) # Long operation
230
return f"Work completed with {self.name}"
231
232
def close(self):
233
if self.is_open:
234
print(f"Closing resource {self.name}")
235
self.is_open = False
236
237
def work_with_resource():
238
resource = Resource("Database")
239
240
try:
241
resource.open()
242
243
# Use timeout for the work operation
244
with timeout.Timeout(2):
245
result = resource.work()
246
return result
247
248
except timeout.Timeout:
249
print("Work operation timed out")
250
return None
251
finally:
252
# Always cleanup
253
resource.close()
254
255
result = work_with_resource()
256
print(f"Final result: {result}")
257
```
258
259
### Nested Timeouts
260
261
```python
262
import gevent
263
from gevent import timeout
264
265
def level3_operation():
266
print("Level 3: Starting")
267
gevent.sleep(1)
268
print("Level 3: Completed")
269
return "Level 3 result"
270
271
def level2_operation():
272
print("Level 2: Starting")
273
274
# Inner timeout (2 seconds)
275
try:
276
with timeout.Timeout(2):
277
result = level3_operation()
278
print("Level 2: Got result from level 3")
279
gevent.sleep(0.5)
280
return f"Level 2 processed: {result}"
281
except timeout.Timeout:
282
print("Level 2: Inner timeout occurred")
283
return "Level 2: Inner timeout result"
284
285
def level1_operation():
286
print("Level 1: Starting")
287
288
# Outer timeout (5 seconds)
289
try:
290
with timeout.Timeout(5):
291
result = level2_operation()
292
print("Level 1: Got result from level 2")
293
return f"Level 1 final: {result}"
294
except timeout.Timeout:
295
print("Level 1: Outer timeout occurred")
296
return "Level 1: Outer timeout result"
297
298
final_result = level1_operation()
299
print(f"Final: {final_result}")
300
```
301
302
### Timeout with Greenlet Coordination
303
304
```python
305
import gevent
306
from gevent import timeout
307
308
def worker(worker_id, work_time):
309
print(f"Worker {worker_id} starting ({work_time}s of work)")
310
gevent.sleep(work_time)
311
print(f"Worker {worker_id} completed")
312
return f"Result from worker {worker_id}"
313
314
def coordinate_workers():
315
workers = [
316
gevent.spawn(worker, 1, 1),
317
gevent.spawn(worker, 2, 3), # This will timeout
318
gevent.spawn(worker, 3, 0.5),
319
]
320
321
results = []
322
323
# Wait for each worker with individual timeouts
324
for i, w in enumerate(workers, 1):
325
try:
326
with timeout.Timeout(2):
327
result = w.get()
328
results.append(result)
329
except timeout.Timeout:
330
print(f"Worker {i} timed out, killing it")
331
w.kill()
332
results.append(f"Worker {i} timeout")
333
334
return results
335
336
results = coordinate_workers()
337
print(f"All results: {results}")
338
```