简体   繁体   English

如何在 asyncio 和 PyQt5 事件循环中使用回调和期货?

[英]How to use callbacks and futures with asyncio and the PyQt5 event loop?

This is a small test program I wrote trying to understand how I can use the PyQt eventloop with asyncio :这是我编写的一个小测试程序,试图了解如何将 PyQt asyncioasyncio一起asyncio

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
from PyQt5 import QtCore
import qasync
import asyncio

async def main():
    app = QApplication(sys.argv)
    asyncio.set_event_loop(qasync.QEventLoop(app))
    window = QMainWindow()
    window.setGeometry(100, 100, 200, 200)
    button = QPushButton(window)
    button.move(50, 50)
    button.resize(100, 100)
    button.setText('Run')
    future = None
    def run_action():
        future.set_result('run clicked')
    button.clicked.connect(run_action)
    window.setWindowTitle('Testing async event loop')
    window.show()
    await asyncio.sleep(1)
    i = 0
    while True:
        future = asyncio.get_event_loop().create_future()
        result = await future
        i += 1
        if i == 4:
            break
    print("Done")

asyncio.run(main())

This gives me the following error:这给了我以下错误:

Traceback (most recent call last):
  File "/home/hakon/test/python/async/./t.py", line 36, in <module>
    asyncio.run(main())
  File "/home/hakon/.pyenv/versions/3.9.4/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/home/hakon/.pyenv/versions/3.9.4/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/home/hakon/test/python/async/./t.py", line 25, in main
    await asyncio.sleep(1)
  File "/home/hakon/.pyenv/versions/3.9.4/lib/python3.9/asyncio/tasks.py", line 654, in sleep
    return await future
RuntimeError: Task <Task pending name='Task-1' coro=<main() running at /home/hakon/test/python/async/./t.py:25> cb=[_run_until_complete_cb() at /home/hakon/.pyenv/versions/3.9.4/lib/python3.9/asyncio/base_events.py:184]> got Future <Future pending> attached to a different loop

Any idea what I am missing here?知道我在这里缺少什么吗? How can I improve this code?如何改进此代码?

The problem is that you are running an eventloop and then you have just created the Qt eventloop.问题是您正在运行一个事件循环,然后您刚刚创建了 Qt 事件循环。 There are 2 possible solutions:有两种可能的解决方案:

  • Set the eventloop before executing the coroutine main:在执行协程 main 之前设置 eventloop:

     import asyncio import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton import qasync async def main(): window = QMainWindow() window.setGeometry(100, 100, 200, 200) button = QPushButton(window) button.move(50, 50) button.resize(100, 100) button.setText("Run") future = None def run_action(): if future is not None: future.set_result("run clicked") button.clicked.connect(run_action) window.setWindowTitle("Testing async event loop") window.show() await asyncio.sleep(1) i = 0 while True: future = asyncio.get_event_loop().create_future() result = await future i += 1 if i == 4: break print("Done") app = QApplication(sys.argv) loop = qasync.QEventLoop(app) asyncio.set_event_loop(loop) with loop: loop.run_until_complete(main())
  • Or use qasync.run():或者使用 qasync.run():

     import asyncio import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton import qasync async def main(): window = QMainWindow() window.setGeometry(100, 100, 200, 200) button = QPushButton(window) button.move(50, 50) button.resize(100, 100) button.setText("Run") future = None def run_action(): if future is not None: future.set_result("run clicked") button.clicked.connect(run_action) window.setWindowTitle("Testing async event loop") window.show() await asyncio.sleep(1) i = 0 while True: future = asyncio.get_event_loop().create_future() result = await future i += 1 if i == 4: break print("Done") qasync.run(main())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM