Asyncio coroutine handling

Viewed 516

I've created a text game in Python which interacts using WebSockets, through Quart. So the server file looks like this:

import asyncio

from quart import Quart, render_template, websocket

import Rpg

app = Quart(__name__,
            static_url_path='',
            static_folder='static',
            template_folder='templates')


@app.route('/')
async def index():
    return await asyncio.get_event_loop().create_task(render_template('index.html'))


@app.websocket('/game')
async def game():
    try:
        task = await Rpg.triggerStartGame(websocket)
        await asyncio.gather(task)
    except GeneratorExit as e:
        await websocket.close(1001)
        print("Coroutine end.")

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=False)

So as you can see there is one endpoint which server an html file which in turn uses the /game endpoint. In general everything is working fine, however after each created instance (that is each time a client gets an html page which connects to /game) I get a warning:

Task was destroyed but it is pending!
task: <Task pending name='Task-44' coro=<ASGIWebsocketConnection.handle_websocket() running at /home/nick/.local/lib/python3.9/site-packages/quart/asgi.py:207> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fc446023790>()]> cb=[gather.<locals>._done_callback() at /usr/lib/python3.9/asyncio/tasks.py:766]>

This was not really bothering me until I found out that after refreshing the page sometimes, it causes the server to crash with the error below:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/nick/.local/lib/python3.9/site-packages/quart/app.py", line 1591, in handle_websocket
    return await self.full_dispatch_websocket(websocket_context)
  File "/home/nick/.local/lib/python3.9/site-packages/quart/app.py", line 1613, in full_dispatch_websocket
    result = await self.handle_user_exception(error)
  File "/home/nick/.local/lib/python3.9/site-packages/quart/app.py", line 968, in handle_user_exception
    raise error
  File "/home/nick/.local/lib/python3.9/site-packages/quart/app.py", line 1611, in full_dispatch_websocket
    result = await self.dispatch_websocket(websocket_context)
  File "/home/nick/.local/lib/python3.9/site-packages/quart/app.py", line 1654, in dispatch_websocket
    return await self.ensure_async(handler)(**websocket_.view_args)
  File "/home/nick/147/TheScript/web/flask/QuartServer.py", line 25, in game
    await websocket.close(1001)
  File "/home/nick/.local/lib/python3.9/site-packages/werkzeug/local.py", line 422, in __get__
    obj = instance._get_current_object()
  File "/home/nick/.local/lib/python3.9/site-packages/werkzeug/local.py", line 544, in _get_current_object
    return self.__local()  # type: ignore
  File "/home/nick/.local/lib/python3.9/site-packages/quart/globals.py", line 26, in _ctx_lookup
    raise RuntimeError(f"Attempt to access {name} outside of a relevant context")
RuntimeError: Attempt to access websocket outside of a relevant context

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/nick/.local/lib/python3.9/site-packages/quart/app.py", line 1674, in finalize_websocket
    response = await self.postprocess_websocket(response, websocket_context)
  File "/home/nick/.local/lib/python3.9/site-packages/quart/app.py", line 1694, in postprocess_websocket
    functions = (websocket_context or _websocket_ctx_stack.top)._after_websocket_functions
AttributeError: 'NoneType' object has no attribute '_after_websocket_functions'
    await self.auto_pop(exc_value)
  File "/home/nick/.local/lib/python3.9/site-packages/quart/ctx.py", line 97, in auto_pop
    await self.pop(exc)
  File "/home/nick/.local/lib/python3.9/site-packages/quart/ctx.py", line 177, in pop
    await self.app.do_teardown_websocket(exc, self)
  File "/home/nick/.local/lib/python3.9/site-packages/quart/app.py", line 1121, in do_teardown_websocket
    for blueprint in _websocket_ctx_stack.top.websocket.blueprints:
AttributeError: 'NoneType' object has no attribute 'websocket'
Task was destroyed but it is pending!
task: <Task pending name='Task-20' coro=<worker_serve.<locals>._server_callback() running at /home/nick/.local/lib/python3.9/site-packages/hypercorn/asyncio/run.py:103> wait_for=<_GatheringFuture pending cb=[<TaskWakeupMethWrapper object at 0x7fc4475baa30>()]>>
Exception ignored in: <coroutine object worker_serve.<locals>._server_callback at 0x7fc4475b76c0>
Traceback (most recent call last):
  File "/home/nick/.local/lib/python3.9/site-packages/hypercorn/asyncio/run.py", line 103, in _server_callback
    await TCPServer(app, loop, config, reader, writer)
  File "/home/nick/.local/lib/python3.9/site-packages/hypercorn/asyncio/tcp_server.py", line 79, in run
    await self._read_data()
RuntimeError: coroutine ignored GeneratorExit
Task was destroyed but it is pending!
task: <Task pending name='Task-22' coro=<_handle() running at /home/nick/.local/lib/python3.9/site-packages/hypercorn/asyncio/context.py:39> wait_for=<_GatheringFuture pending cb=[<TaskWakeupMethWrapper object at 0x7fc446012730>()]> cb=[gather.<locals>._done_callback() at /usr/lib/python3.9/asyncio/tasks.py:766]>

I've tried a lot of things I found on searching the error or searching things like "asyncio kill a coroutine" but nothing seems to work. What I need is to kill coroutines which fail without the server stopping to work.

Any ideas? Thanks in advance!

0 Answers
Related