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!