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

带类型注解的异步装饰器结合asyncio.run的mypy类型错误问题

async装饰器的mypy类型报错问题

问题代码

from typing import Awaitable, Callable, ParamSpec, TypeVar
import asyncio

P = ParamSpec("P")
R = TypeVar("R")


def a_decorator(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[R]]:
    async def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
        print("wrapped")
        return await func(*args, **kwargs)

    return _wrapper


@a_decorator
async def just_a_function(value1: int) -> bool:
    print(value1)
    return isinstance(value1, int)


# mypy报错:
# Argument 1 to "run" has incompatible type "Awaitable[bool]"; expected "Coroutine[Any, Any, <nothing>]"  [arg-type]
asyncio.run(just_a_function(10))

报错原因

asyncio.run()的参数类型要求是Coroutine[Any, Any, T],而你定义的装饰器返回的是更宽泛的Callable[P, Awaitable[R]]。尽管Coroutine是Awaitable的子类,但mypy对该场景的类型检查较为严格——它需要明确的协程类型,而非通用的可等待对象类型。

解决方案

调整装饰器的类型标注,将返回值的Awaitable[R]替换为具体的Coroutine[Any, Any, R],让类型匹配asyncio.run()的要求:

from typing import Callable, ParamSpec, TypeVar, Coroutine, Any
import asyncio

P = ParamSpec("P")
R = TypeVar("R")


def a_decorator(func: Callable[P, Coroutine[Any, Any, R]]) -> Callable[P, Coroutine[Any, Any, R]]:
    async def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
        print("wrapped")
        return await func(*args, **kwargs)

    return _wrapper


@a_decorator
async def just_a_function(value1: int) -> bool:
    print(value1)
    return isinstance(value1, int)


asyncio.run(just_a_function(10))  # mypy不再报错

选择建议

不要保持原有的Awaitable[R]标注,应该遵循mypy的提示调整为Coroutine类型。这样做既能通过类型检查,也能让代码的类型约束更精确——毕竟被装饰的是async def定义的协程函数,返回的本来就是协程对象,而非通用的可等待对象。

如果你的装饰器需要兼容返回Future等其他Awaitable类型的函数,可以在调用asyncio.run()时添加类型忽略注释# type: ignore[arg-type],但这属于妥协方案,优先推荐精确匹配协程类型的写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:31:32