如何将类型注释添加到asyncio.Task

Yuv*_*uss 6 python python-3.x type-annotation python-asyncio

我有一个代码如下:

import asyncio
from typing import List

def some_callback(result):
    print(result)

async def b() -> List[int]:
    return [1, 2, 3]

async def a() -> None:
    search = asyncio.ensure_future(b())
    search.add_done_callback( some_callback)
    await search

loop = asyncio.get_event_loop()
loop.run_until_complete(a())
loop.close()
Run Code Online (Sandbox Code Playgroud)

我试图在some_callback函数中添加类型注释,但我无法完全理解hoe来注释result变量.应该是Coroutine吗?或许Awaitable

当我使用reveal_typeof时mypy,关于result变量的输出是Any.

该程序的输出是:

<Task finished coro=<b() done, defined at ____.py:7> result=[1, 2, 3]>
Run Code Online (Sandbox Code Playgroud)

我该如何正确记录这个功能?

Mik*_*mov 6

通常,您只需打印某些变量的类型即可获得其基本注释:

def some_callback(result):
    print(type(result))
Run Code Online (Sandbox Code Playgroud)

虽然它会显示一些内部<class '_asyncio.Task'>类型,但看起来我们可以将其视为常规asyncio.Task

def some_callback(result):
    print(type(result) is asyncio.Task)  # True
Run Code Online (Sandbox Code Playgroud)

但正如您所指出的,我们还可以使用更抽象的类型,因为Taskis (子类) :AwaitableTaskAwaitable

print(issubclass(asyncio.Task, typing.Awaitable))  # True
Run Code Online (Sandbox Code Playgroud)

我们的选择现在缩小到Task或其父类之一Awaitable(包括最极端的情况 -Any这是任何类的父类,并且是 mypy 向您建议的)。

add_done_callbackisFuture方法,根据文档将接收 future 对象作为它的参数。它不会是任何类型的Awaitable(如协程),而只是Future或其中一些子类,如Task.

在选择类型注释时,对函数可以接受的参数(正常工作)进行最抽象的描述以及对它可以返回的内容进行最具体的描述是有意义的。因此,在FutureTask我更喜欢之间进行选择Future(假设您不会Task仅使用特定的属性)。按照这个逻辑,最终的答案是:

def some_callback(result: asyncio.Future):
    print(result)
Run Code Online (Sandbox Code Playgroud)

这一切听起来有点复杂且耗时,但是一旦您有了想法,您将能够更快地选择注释。