You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.11中自定义Awaitable对象报错的最优重构方案

解决Python 3.11中asyncio.wait对自定义可等待对象的兼容性问题

问题原因

Python 3.11对asyncio.wait的底层实现做了调整:不再接受仅实现__await__方法的自定义可等待对象,要求传入的必须是Future/Task类的实例(这类对象自带add_done_callback方法)。Python 3.10的实现允许兼容这类自定义可等待对象,但3.11移除了该兼容逻辑,且未触发弃用警告,导致代码迁移后直接报错。

推荐的重构方式

方式一:用asyncio.create_task包装可等待对象(最直接)

无需修改自定义可等待类的实现,只需在调用asyncio.wait时,将每个自定义可等待对象用asyncio.create_task包装为Task实例即可:

import asyncio

class ExampleAwaitable:
    def __await__(self):
        async def _():
            return await asyncio.sleep(0)
        return _().__await__()

print(f"{asyncio.iscoroutine(ExampleAwaitable())=}")

async def amain():
    # 用create_task包装每个可等待对象
    await asyncio.wait([asyncio.create_task(ExampleAwaitable())])
    print("waited!")

asyncio.run(amain())

方式二:让自定义类继承asyncio.Future(更彻底)

如果你的自定义可等待对象需要支持Future的回调、结果设置等特性,可以直接继承asyncio.Future,并在内部实现异步逻辑:

import asyncio

class ExampleAwaitable(asyncio.Future):
    def __init__(self):
        super().__init__()
        # 启动内部异步任务,完成后设置结果
        asyncio.create_task(self._run())
    
    async def _run(self):
        await asyncio.sleep(0)
        self.set_result(None)

print(f"{asyncio.iscoroutine(ExampleAwaitable())=}")

async def amain():
    await asyncio.wait([ExampleAwaitable()])
    print("waited!")

asyncio.run(amain())

选择建议

  • 若只是为了快速兼容Python 3.11+,优先用方式一,改动最小;
  • 若自定义可等待对象需要具备Future的扩展能力(比如添加回调、手动设置结果),则用方式二。

内容的提问来源于stack exchange,提问作者Grismar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 23:22:45