首页 > 解决方案 > 哪个 python 静态检查器可以捕获“被遗忘的等待”问题?

问题描述

代码:

from typing import AsyncIterable

import asyncio


async def agen() -> AsyncIterable[str]:
    print('agen start')
    yield '1'
    yield '2'


async def agenmaker() -> AsyncIterable[str]:
    print('agenmaker start')
    return agen()


async def amain():
    print('amain')
    async for item in agen():
        pass
    async for item in await agenmaker():
        pass
    # Error:
    async for item in agenmaker():
        pass


def main():
    asyncio.get_event_loop().run_until_complete(amain())


if __name__ == '__main__':
    main()

如您所见,它是类型注释的,并且包含一个容易遗漏的错误。

但是,既没有pylint也没有mypy发现那个错误。

除了单元测试之外,还有哪些选项可以捕获此类错误?

标签: pythonpylintmypy

解决方案


MyPy 完全有能力发现这个问题。问题是未检查未注释的函数。将违规函数注释-> None为正确检查和拒绝。

# annotated with return type
async def amain() -> None:
    print('amain')
    async for item in agen():
        pass
    async for item in await agenmaker():
        pass
    # Error:
    async for item in agenmaker(): # error: "Coroutine[Any, Any, AsyncIterable[str]]" has no attribute "__aiter__" (not async iterable)

        pass

如果您想消除此类问题,请使用标志--disallow-untyped-defs--check-untyped-defs.


MyPy:函数签名和动态与静态类型

一个没有类型注解的函数被 mypy 认为是动态类型的:

def greeting(name):
    return 'Hello ' + name

默认情况下,mypy 不会对动态类型函数进行类型检查。这意味着除了少数例外,mypy 不会在常规未注释的 Python 中报告任何错误。


推荐阅读