0
# Event Loop Integration
1
2
Qt-compatible asyncio event loop that enables coroutines and asyncio functionality to run directly inside Qt application event loops. The QEventLoop class provides a complete implementation of PEP 3156 that integrates seamlessly with Qt's event processing.
3
4
## Capabilities
5
6
### Core Event Loop
7
8
Creates an asyncio-compatible event loop that integrates with Qt's QApplication event loop, allowing async/await syntax and asyncio functionality to work within Qt applications.
9
10
```python { .api }
11
class QEventLoop:
12
"""
13
Implementation of asyncio event loop that uses the Qt Event loop.
14
15
Args:
16
app: QApplication instance (defaults to QApplication.instance())
17
set_running_loop: Deprecated parameter for backwards compatibility
18
already_running: If True, assumes the Qt application is already running
19
"""
20
def __init__(self, app=None, set_running_loop=False, already_running=False): ...
21
```
22
23
#### Usage Example
24
25
```python
26
import asyncio
27
import sys
28
from PySide6.QtWidgets import QApplication
29
from qasync import QEventLoop
30
31
async def main():
32
print("Hello from async coroutine!")
33
await asyncio.sleep(1)
34
print("Async operation complete!")
35
36
app = QApplication(sys.argv)
37
loop = QEventLoop(app)
38
39
# Method 1: Run until complete
40
loop.run_until_complete(main())
41
42
# Method 2: Use modern asyncio.run with loop factory
43
asyncio.run(main(), loop_factory=lambda: QEventLoop(app))
44
```
45
46
### Event Loop Control
47
48
Methods for controlling the event loop lifecycle, including starting, stopping, and managing the loop state.
49
50
```python { .api }
51
def run_forever(self):
52
"""
53
Run eventloop forever.
54
55
Raises:
56
RuntimeError: If event loop is already running
57
"""
58
59
def run_until_complete(self, future):
60
"""
61
Run until Future is complete.
62
63
Args:
64
future: Coroutine or Future to run to completion
65
66
Returns:
67
Result of the future
68
69
Raises:
70
RuntimeError: If event loop is already running or stops before completion
71
"""
72
73
def stop(self):
74
"""Stop event loop."""
75
76
def close(self):
77
"""
78
Release all resources used by the event loop.
79
The loop cannot be restarted after it has been closed.
80
81
Raises:
82
RuntimeError: If called on a running event loop
83
"""
84
85
def is_running(self):
86
"""
87
Return True if the event loop is running, False otherwise.
88
89
Returns:
90
bool: Current running state
91
"""
92
```
93
94
### Callback Scheduling
95
96
Schedule callbacks to run at specific times or as soon as possible within the event loop.
97
98
```python { .api }
99
def call_soon(self, callback, *args, context=None):
100
"""
101
Register a callback to be run on the next iteration of the event loop.
102
103
Args:
104
callback: Function to call
105
*args: Arguments to pass to callback
106
context: Optional contextvars.Context
107
108
Returns:
109
asyncio.Handle: Handle that can be used to cancel the callback
110
"""
111
112
def call_later(self, delay, callback, *args, context=None):
113
"""
114
Register callback to be invoked after a certain delay.
115
116
Args:
117
delay: Delay in seconds
118
callback: Function to call
119
*args: Arguments to pass to callback
120
context: Optional contextvars.Context
121
122
Returns:
123
asyncio.Handle: Handle that can be used to cancel the callback
124
125
Raises:
126
TypeError: If callback is a coroutine function or not callable
127
"""
128
129
def call_at(self, when, callback, *args, context=None):
130
"""
131
Register callback to be invoked at a certain time.
132
133
Args:
134
when: Absolute time when to run callback (from time.monotonic())
135
callback: Function to call
136
*args: Arguments to pass to callback
137
context: Optional contextvars.Context
138
139
Returns:
140
asyncio.Handle: Handle that can be used to cancel the callback
141
"""
142
143
def time(self):
144
"""
145
Get time according to event loop's clock.
146
147
Returns:
148
float: Current time from time.monotonic()
149
"""
150
```
151
152
### Thread-Safe Operations
153
154
Enable thread-safe interaction with the event loop from other threads.
155
156
```python { .api }
157
def call_soon_threadsafe(self, callback, *args, context=None):
158
"""
159
Thread-safe version of call_soon.
160
161
Args:
162
callback: Function to call
163
*args: Arguments to pass to callback
164
context: Optional contextvars.Context
165
"""
166
167
def run_in_executor(self, executor, callback, *args):
168
"""
169
Run callback in executor.
170
171
Args:
172
executor: Executor instance (uses default QThreadExecutor if None)
173
callback: Function to run in executor
174
*args: Arguments to pass to callback
175
176
Returns:
177
asyncio.Future: Future representing the execution
178
"""
179
180
def set_default_executor(self, executor):
181
"""
182
Set the default executor for run_in_executor calls.
183
184
Args:
185
executor: Executor instance implementing concurrent.futures.Executor interface
186
"""
187
```
188
189
### Error Handling
190
191
Configure how the event loop handles exceptions that occur during callback execution.
192
193
```python { .api }
194
def set_exception_handler(self, handler):
195
"""
196
Set custom exception handler for the event loop.
197
198
Args:
199
handler: Function that takes (loop, context) parameters
200
"""
201
202
def default_exception_handler(self, context):
203
"""
204
Handle exceptions using the default behavior.
205
206
Args:
207
context: Dictionary containing exception information
208
"""
209
210
def call_exception_handler(self, context):
211
"""
212
Call the configured exception handler.
213
214
Args:
215
context: Dictionary containing exception information
216
"""
217
```
218
219
### Debug Support
220
221
Methods for debugging and monitoring event loop behavior.
222
223
```python { .api }
224
def get_debug(self):
225
"""
226
Get debug mode status.
227
228
Returns:
229
bool: True if debug mode is enabled
230
"""
231
232
def set_debug(self, enabled):
233
"""
234
Set debug mode for the event loop.
235
236
Args:
237
enabled: Whether to enable debug mode
238
"""
239
```
240
241
## Platform-Specific Implementations
242
243
### Unix/Linux (QSelectorEventLoop)
244
245
Uses a selector-based approach with QSocketNotifier for file descriptor monitoring, compatible with asyncio.SelectorEventLoop.
246
247
### Windows (QIOCPEventLoop)
248
249
Uses I/O Completion Ports (IOCP) through a proactor pattern, compatible with asyncio.ProactorEventLoop.
250
251
## Context Manager Support
252
253
```python { .api }
254
def __enter__(self):
255
"""Context manager entry."""
256
257
def __exit__(self, *args):
258
"""Context manager exit - stops and closes the loop."""
259
```
260
261
#### Usage Example
262
263
```python
264
async def main():
265
await asyncio.sleep(1)
266
print("Task complete!")
267
268
app = QApplication(sys.argv)
269
270
with QEventLoop(app) as loop:
271
loop.run_until_complete(main())
272
# Loop is automatically stopped and closed
273
```