pythonpython-asynciowindows-subsystem-for-linuxcoap

Asyncio.run gives RuntimeError loop is closed


When trying to create simple coap server with asyncronous function and asyncio.run it return Event loop is closed. Code below:

import aiocoap
import aiocoap.resource as resource


class CoAPServer(resource.Resource):
    def __init__(self) -> None:
        super().__init__()

    async def render_get(self, request):
        print("Received GET request ...")
        return aiocoap.Message(code=aiocoap.GET, payload="hello friend".encode('utf8'))

    async def render_post(self, request):
        print("Received POST request ...")
        return aiocoap.Message(code=aiocoap.CHANGED, payload="that's me".encode('utf8'))

async def main():
    root = resource.Site()
    root.add_resource(['demo'], CoAPServer)
    task = asyncio.create_task(aiocoap.Context.create_server_context(root, bind=('127.0.0.1', 5683)))
    await task

if __name__ == "__main__":
    asyncio.run(main())

Gives this error:

Exception ignored in: <function RecvmsgSelectorDatagramTransport.__del__ at 0x7f9a04c57310>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/aiocoap/util/asyncio/recvmsg.py", line 95, in __del__
    self.close()
  File "/usr/local/lib/python3.8/dist-packages/aiocoap/util/asyncio/recvmsg.py", line 83, in close
    self._loop.call_soon(self._protocol.connection_lost, None)
  File "/usr/lib/python3.8/asyncio/base_events.py", line 719, in call_soon
    self._check_closed()
  File "/usr/lib/python3.8/asyncio/base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

Instead, if i use get_event_loop().run_forever() which is not recommended as per the docs

Application developers should typically use the high-level asyncio functions, such as asyncio.run(), and should rarely need to reference the loop object or call its methods. This section is intended mostly for authors of lower-level code, libraries, and frameworks, who need finer control over the event loop behavior.

if __name__ == "__main__":
    asyncio.get_event_loop().run_forever()

it works. Currently using python3.8.10 in wsl


Solution

  • This is an issue resulting from aiocoap still using (and, in some places, using badly) idioms to support Python 3.7 or (in obsoleted parts) even previous versions.

    I'm aware asyncio.run() is preferred, but until the next aiocoap release (in which I plan to update the examples too), the old idiom is what works best across the range of supported Python versions.