将异步函数作为函数参数的 Python 类型提示

问题描述 投票:0回答:2

我试图确保函数参数是异步函数。 所以我正在使用以下代码:

async def test(*args, **kwargs):
    pass

def consumer(function_: Optional[Coroutine[Any, Any, Any]]=None):
    func = function_

consumer(test)

但这不起作用。

在 PyCharm 中进行类型检查时出现以下错误:

Expected type 'Optional[Coroutine]', got '(args: Tuple[Any, ...], kwargs: Dict[str, Any]) -> Coroutine[Any, Any, None]' instead

任何人都可以给我一些如何解决这个问题的提示吗?

python pycharm python-asyncio type-hinting
2个回答
44
投票

您正在寻找:

FuncType = Callable[[Any, Any], Awaitable[Any]]
def consumer(function_: FuncType = None):
    pass  # TODO: do stuff

为什么类型是这样的结构?如果您声明一个函数

async
,您实际上所做的是将其包装在具有给定参数的新函数中,该函数返回一个
Coroutine


由于这可能与某些来到这里的人相关,因此这是一个具有 in 和 out 类型的

await
可用函数类型的示例:

OnAction = Callable[[Foo, Bar], Awaitable[FooBar]]

这是一个接受

Foo
Bar
并返回
FooBar

的函数

14
投票

我帮不了你太多,特别是因为现在(PyCharm 2018.2)这个错误不再在 Pycharm 中出现。

目前,类型提示介于用于反射/内省的可靠元数据和接受用户输入的任何内容的美化注释之间。对于普通数据结构来说,这很棒(我的同事甚至制作了一个基于打字的验证框架),但事情变得更多当回调和异步函数发挥作用时会变得复杂。

看看这些问题:

https://github.com/python/typing/issues/424(从今天开始开放)- 异步输入 https://github.com/python/mypy/issues/3028(从今天开始)- var-args 可调用类型

我会选择:

from typing import Optional, Coroutine, Any, Callable


async def test(*args, **kwargs):
    return args, kwargs


def consumer(function_: Optional[Callable[..., Coroutine[Any, Any, Any]]] = None):
    func = function_
    return func


consumer(test)

我不能保证他们的意思正是如此,但我的提示是这样构建的:

Optional
- 当然,可以是
None
或其他什么,在这种情况下:

Callable
- 可以用
()
调用的东西,
...
代表任何参数,它会产生:

Coroutine[Any, Any, Any]
- 这是从OP复制的,非常通用。您建议这个
function_
可能会被
await
编辑,但也会收到
send()
consumer
编辑内容,并被
next()
编辑/迭代。情况很可能是这样,但是...

如果只是

await
编辑,那么最后一部分可能是:

Awaitable[Any]
,如果你真的在等待某事或

Awaitable[None]
,如果回调没有返回任何内容,而你只希望
await
它。

注意:您的

consumer
不是
async
。它不会真正
await
你的
function_
,但要么
yield from
它,或者做一些
loop.run_until_complete()
.create_task()
,或
.ensure_future()

© www.soinside.com 2019 - 2024. All rights reserved.