哪个 python 静态检查器可以捕获 'forgotten await' 问题?
Which python static checker can catch 'forgotten await' problems?
代码:
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
都没有发现该错误。
除了单元测试之外,还有哪些选项可以捕获此类错误?
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
or --check-untyped-defs
。
MyPy: Function signatures and dynamic vs static typing
A function without type annotations is considered to be dynamically typed by mypy:
def greeting(name):
return 'Hello ' + name
By default, mypy will not type check dynamically typed functions. This means that with a few exceptions, mypy will not report any errors with regular unannotated 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
都没有发现该错误。
除了单元测试之外,还有哪些选项可以捕获此类错误?
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
or --check-untyped-defs
。
MyPy: Function signatures and dynamic vs static typing
A function without type annotations is considered to be dynamically typed by mypy:
def greeting(name): return 'Hello ' + name
By default, mypy will not type check dynamically typed functions. This means that with a few exceptions, mypy will not report any errors with regular unannotated Python.