【问题标题】:Asyncio.run gives RuntimeError loop is closedAsyncio.run 给出 RuntimeError 循环关闭
【发布时间】:2021-11-16 15:15:29
【问题描述】:

当尝试使用异步函数和 asyncio.run 创建简单的 coap 服务器时,它返回事件循环已关闭。代码如下:

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

给出这个错误:

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

相反,如果我使用 get_event_loop().run_forever() 根据文档不推荐

应用程序开发人员通常应该使用高级异步函数,例如 asyncio.run(),并且很少需要引用循环对象或调用其方法。本部分主要面向需要更好地控制事件循环行为的低级代码、库和框架的作者。

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

它有效。目前在wsl中使用python3.8.10

【问题讨论】:

    标签: python python-asyncio wsl-2 coap


    【解决方案1】:

    这是由于 aiocoap 仍在使用(并且在某些地方使用不当)惯用语来支持 Python 3.7 或(在已过时的部分)甚至以前的版本所导致的问题。

    我知道asyncio.run() 是首选,但在下一个 aiocoap 版本(我也计划在其中更新示例)之前,旧习语在受支持的 Python 版本范围内最有效。

    【讨论】:

    • 抱歉并不是要对我引用的最佳实践感到讨厌,我只是想弄清楚我是否应该受到指责,是文档还是其他原因。非常感谢您的工作!
    • 一点也不讨厌,这是一个正确的观点,责任在于我仍然在采用现代异步。
    • 最新状态(尚未发布,但在 master 分支中)修复了您指出的问题以及其他一些问题;如果您现在发现与 asyncio.run() 一起使用时出现任何问题,请打开一个错误。 (或者任何起作用的东西,真的:-))
    【解决方案2】:

    asyncio.run(main()) 的代码在 Unix 系统上运行良好。因此,aiocoap 如何处理 WSL 环境中的事件循环很可能是个问题。现在,您最好使用asyncio.get_event_loop().run_forever(),直到维护人员修补库。

    【讨论】:

    • 即使在 Linux 系统上,asyncio.run() 也有一些奇怪之处,例如。使用 Ctrl-C 中断程序时。我认为这源于我如何尝试解决 pre-.run() asyncio 的一些有问题的方面,例如。通过手动处理 KeyboardInterrupt。
    猜你喜欢
    • 2020-08-15
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 1970-01-01
    • 2019-01-04
    相关资源
    最近更新 更多