3

This is a small test program I wrote trying to understand how I can use the PyQt eventloop with 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?

1
  • I'm not sure, but you may need to use asyncio.set_event_loop before asyncio.run(main()). Commented Jul 18, 2021 at 20:40

1 Answer 1

3

The problem is that you are running an eventloop and then you have just created the Qt eventloop. There are 2 possible solutions:

  • Set the eventloop before executing the coroutine main:

    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():

    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())
    
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.