asyncio create task and aiohttp , 'no running event loop'

Question:

Im trying to make a Pyqt5 app with aiohttp request, and asyncio tasks.
Im using quamash package too and it requires Python 3.7 so i installed this version.(it didn’t work on Python 3.10) The main reason i use asyncio and quamash is because i want to do requests and without freezing the GUI of the app.

I get this error when i click the Start button and close the app:

Task exception was never retrieved
future: <Task finished coro=<App.rotator() done, defined at C:UsersZsoltDocumentspython-examplestack_exmaple.py:37> exception=RuntimeError('no running event loop')>
Traceback (most recent call last):
  File "C:UsersZsoltDocumentspython-examplestack_exmaple.py", line 41, in rotator
    response = await get()
  File "C:UsersZsoltDocumentspython-examplestack_exmaple.py", line 51, in get
    async with session.get(pokemon_url) as resp:
  File "C:UsersZsoltAppDataLocalProgramsPythonPython37libsite-packagesaiohttpclient.py", line 1138, in __aenter__
    self._resp = await self._coro
  File "C:UsersZsoltAppDataLocalProgramsPythonPython37libsite-packagesaiohttpclient.py", line 533, in _request
    async with ceil_timeout(real_timeout.connect):
  File "C:UsersZsoltAppDataLocalProgramsPythonPython37libsite-packagesaiohttphelpers.py", line 734, in ceil_timeout
    return async_timeout.timeout(None)
  File "C:UsersZsoltAppDataLocalProgramsPythonPython37libsite-packagesasync_timeout__init__.py", line 30, in timeout
    loop = _get_running_loop()
  File "C:UsersZsoltAppDataLocalProgramsPythonPython37libsite-packagesasync_timeout__init__.py", line 236, in _get_running_loop
    return asyncio.get_running_loop()
RuntimeError: no running event loop

Here is the full code:

from PyQt5.QtWidgets import *
from PyQt5.QtGui import QKeySequence, QPalette, QColor
from PyQt5.QtCore import Qt
from PyQt5 import QtGui, QtCore
import asyncio
import aiohttp
import quamash
import os.path
import json
import sys

class App(QWidget):

    run = 0
    response = ''
    def __init__(self, loop):
        super().__init__()

        btn = QPushButton('Start', self)
        btn.resize(btn.sizeHint())
        btn.clicked.connect(self.start)

        self.setGeometry(200, 200, 700, 400)
        self.display = QLabel(self)
        self.display.resize(200, 500)
        self.display.move(1, 50)

        self.count = 0
        self.show()
        self.loop = loop
        self.tasks = []
        self.tasks.append(loop.create_task(self.rotator()))

    async def rotator(self):
        while await asyncio.sleep(0, True):
            if (self.run == 1):
                self.count += 1
                response = await get()
                self.display.setText(str(response))
                  
    def start (self):
        self.run = 1            

async def get():
    async with aiohttp.ClientSession() as session:
        pokemon_url = 'https://pokeapi.co/api/v2/pokemon/151'
        async with session.get(pokemon_url) as resp:
            pokemon = await resp.json()
            print(pokemon)
            return pokemon
      
app = QApplication(sys.argv)
app.setApplicationName("Sample ;)")

loop = quamash.QEventLoop(app)
asyncio.set_event_loop(loop)

with loop:
    window = App(loop)
    window.show()
    loop.run_forever()

If i comment out the response = await get() it works, it counts the self.count += 1 and it shows the variable on self.display.setText(str(self.count)) . But i need to get it to work with the aiohttp request so it should print out the response from the request.

Answers:

If using the quamash package:

I fixed the error by installing previous release of aiohttp
Orignally i had aiohttp 3.8.1.dist installed. I also knew it was working for me before on other version of aiohttp, so i looked up pypi.org/project/aiohttp/#history and turn out i had to uninstall aiohttp and install aiohttp==3.7.4.

Commands:

pip uninstall aiohttp
pip install aiohttp==3.7.4

TLDR; replace quamash with qasync

In asyncio, a task always exists when async code is executed. Like in a multithreaded program at least the main thread is present. If quamash doesn’t follow the rule — it is not aiohttp problem.

quamash is not maintained anymore, the latest release was made 3.5 years ago.
The maintained successor is qasync which has no this bug and works with the latest aiohttp perfectly fine.

Answered By: Andrew Svetlov

FWIW, you may also use the qtinter package to replace quamash, which supports Python 3.7 to 3.11. (Disclaimer: I’m the author of qtinter.)

With qtinter the last few lines need to be changed to the following:

app = QApplication(sys.argv)
app.setApplicationName("Sample ;)")

with qtinter.using_asyncio_from_qt():
    window = App(asyncio.get_running_loop())
    window.show()
    app.exec()
Answered By: fancidev