I've got a situation where I would like to connect an async function that uses awaits to the clicked signal of a QPushButton.
The motivation is that I need to manage some io-bound stuff and using awaits seems to be the most cogent way to do that. The problem is that when one uses awaits, the invoking function needs to be marked as async and so do all functions that invoke THAT function. This "bubbles up to the top" until eventually, there's a button clicked signal that needs to be connected to an async slot function. I am not sure how to do that and there's not much advice. Maybe I got the wrong idea and pyQt6 isn't supposed to mix with asyncio?
Here's an example. It's just a QMainWindow with a button, and I am trying to connect the button's clicked signal to a slot function that happens to be async. It just prints numbers and uses asyncio.sleep(1.0)
to wait for 1 second after printing each number.
import sys
import asyncio
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
button = QPushButton("Press This")
self.setCentralWidget(button)
button.clicked.connect(self.my_async_func)
async def my_async_func(self):
for x in range(1,10):
print(x)
await asyncio.sleep(1.0)
print("all done")
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
When I click the button I get the following, and of course, nothing prints.
RuntimeWarning: coroutine 'MainWindow.my_async_func' was never awaited
app.exec()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
How do I tell connect(...)
that I want to use an async function?
My previous experience was coming from .net WPF and I was hoping that it would not be a big deal to tie an async function to a UI event.