为什么在mypy中使用await表达式会得到无效的语法?

时间:2018-08-08 12:26:18

标签: python python-asyncio mypy

# file test.py
import asyncio
from inspect import iscoroutine
from typing import Any


async def a():
    print('run a')
    asyncio.sleep(1)
    return 1


async def b():
    # type: () -> Any
    print('run b')
    return a()


async def g():
    # type: () -> Any
    print('run g')
    s = b()
    while iscoroutine(s):
        print('in g', s)
        s = await s
    return s


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    a = loop.run_until_complete(g())
    print('finish ', a)

使用python3.6.6运行上述代码时,我得到了:

run g
in g <coroutine object b at 0x10a980938>
run b
in g <coroutine object a at 0x10a95d620>
run a
finish  1

Process finished with exit code 0

似乎一切都很好。但是运行mypy test.py时,我得到了test.py:24: error: invalid syntax。这是什么意思? 我的代码有问题吗? 我的python解释器版本为3.6.6,mypy版本为0.620。

1 个答案:

答案 0 :(得分:2)

嗯,这很奇怪!

我认为这是typed_ast中的一个错误,mypy库用于将Python源代码转换为抽象语法树。

我能够将您的问题简化为以下内容:

import asyncio

async def g():
    # type: () -> None
    await asyncio.sleep(1)

这还会在包含“ await”的行上出现语法错误。

但是,如果执行此操作,错误消息就会消失:

import asyncio

async def g() -> None:
    await asyncio.sleep(1)

相同的解决方法(使用类型提示语法而不是注释语法也可以解决原始程序的问题)。似乎由于某种原因,基于注释的类型签名语法和'await'关键字不能很好地交互。

我怀疑这个问题没有早发现的原因是因为大多数使用异步/等待的人也在使用Python 3的内置注释语法-类型注释语法通常在您希望与Python兼容时使用2,但async / await仅适用于Python 3 ...

无论如何,我建议在mypy或typed_ast的问题跟踪器上提交问题-mypy团队监视并维护这两个存储库。 (或者,如果您愿意并且有一些空闲时间,甚至可以尝试自己解决typed_ast中的问题?这感觉上像是一个疏忽,对我来说是一个棘手的错误。)