V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
ray1888
V2EX  ›  Python

asyncio 的 await 回调需要的条件是什么?

  •  
  •   ray1888 ·
    ray1888 · 2017-06-15 15:54:57 +08:00 · 6697 次点击
    这是一个创建于 2754 天前的主题,其中的信息可能已经有所发展或是发生改变。

    1 import asyncio 2 3 def addone(x,y): 4 x = x+1 5 y = y+1 6 print("x={}".format(x)) 7
    8 async def compute(x, y): 9 print('Compute {} + {} ...'.format(x, y)) 10 #await asyncio.sleep(1.0) 11 await addone(x,y) 12 return x + y 13
    14 async def print_sum(x, y): 15 result = await compute(x, y) 16 print('{} + {} = {}'.format(x, y, result)) 17
    18 loop = asyncio.get_event_loop() 19 loop.run_until_complete(print_sum(1, 2)) 20 loop.close()

    上面这样的代码报出来结果是这样 await addone(x,y) TypeError: object int can't be used in 'await' expression

    但是如果改成这样 1 import asyncio 2 3 def addone(x,y): 4 x = x+1 5 y = y+1 6
    7
    8 async def compute(x, y): 9 print('Compute {} + {} ...'.format(x, y)) 10 await asyncio.sleep(1.0) 11 #await addone(x,y) 12 return x + y 13
    14 async def print_sum(x, y): 15 result = await compute(x, y) 16 print('{} + {} = {}'.format(x, y, result)) 17
    18 loop = asyncio.get_event_loop() 19 loop.run_until_complete(print_sum(1, 2)) 20 loop.close()

    第二种就不会报错,那么 await 后面只能调用异步的函数吗?求大神解答

    11 条回复    2017-06-18 03:47:07 +08:00
    kindjeff
        1
    kindjeff  
       2017-06-15 15:57:12 +08:00 via iPhone
    是的
    ray1888
        2
    ray1888  
    OP
       2017-06-15 15:58:30 +08:00
    帖子代码格式出了问题,我尝试重新贴一下
    1 import asyncio
    2
    3 def addone(x,y):
    4 x = x+1
    5 y = y+1
    6 print("x={}".format(x))
    7
    8 async def compute(x, y):
    9 print('Compute {} + {} ...'.format(x, y))
    10 #await asyncio.sleep(1.0)
    11 await addone(x,y)
    12 return x + y
    13
    14 async def print_sum(x, y):
    15 result = await compute(x, y)
    16 print('{} + {} = {}'.format(x, y, result))
    17
    18 loop = asyncio.get_event_loop()
    19 loop.run_until_complete(print_sum(1, 2))
    20 loop.close()

    第一段的代码

    报错如下:await addone(x,y) TypeError: object int can't be used in 'await' expression
    ray1888
        3
    ray1888  
    OP
       2017-06-15 16:00:59 +08:00
    1 import asyncio
    2
    3 def addone(x,y):
    4 x = x+1
    5 y = y+1
    6 print("x={}".format(x))
    7
    8 async def compute(x, y):
    9 print('Compute {} + {} ...'.format(x, y))
    10 await asyncio.sleep(1.0)
    11 #await addone(x,y)
    12 return x + y
    13
    14 async def print_sum(x, y):
    15 result = await compute(x, y)
    16 print('{} + {} = {}'.format(x, y, result))
    17
    18 loop = asyncio.get_event_loop()
    19 loop.run_until_complete(print_sum(1, 2))
    20 loop.close()

    这样就不会报错,那么我只能调用异步的函数吗?如果是,那如何知道哪些内置的函数支持异步?
    dishonest
        4
    dishonest  
       2017-06-15 16:02:11 +08:00
    去掉 11 行的 await
    ray1888
        5
    ray1888  
    OP
       2017-06-15 16:16:34 +08:00
    @dishonest 其实就是想问 await 后面能接什么函数而已,如果打掉 11 行的 await,就相当于让渡之后拿到控制权的函数线性执行
    mxi1
        6
    mxi1  
       2017-06-15 16:20:32 +08:00 via iPhone
    await 必须是 async 的方法吧,3.5 之前是通过 decorator 的方式实现的,你读读当时的文档,应该有介绍原理的
    zhengxiaowai
        7
    zhengxiaowai  
       2017-06-15 16:21:53 +08:00
    跟 coroutine object
    kindjeff
        8
    kindjeff  
       2017-06-15 16:21:57 +08:00
    @ray1888 你写的几个函数就是应该让他们一直执行啊,IO 操作的时候你才应该用 await 把执行权给别的位置。await 后面应该接一个 awaitable 的东西。
    ray1888
        9
    ray1888  
    OP
       2017-06-15 16:32:31 +08:00
    @kindjeff 所以是 await 函数接的是 IO 操作对应的函数?不是很懂
    AX5N
        10
    AX5N  
       2017-06-16 01:03:22 +08:00
    “第二种就不会报错,那么 await 后面只能调用异步的函数吗?求大神解答”
    NoAnyLove
        11
    NoAnyLove  
       2017-06-18 03:47:07 +08:00
    代码排版看得头痛,直接跳过了。如果只看标题的话,一个用于 await 语句的对象必须是 awaitable 的,即实现了`__await__`方法,对应的 abc 是 collections.abc.Awaitable,可以用`isinstance(gencoro, Awaitable)`进行判断。

    此外,基于生成器的 coroutine 对象(用 types.coroutine 和 asyncio.coroutine 修饰器修饰),虽然没有实现`__await__`方法,但是也被认为是 awaitable 的,可以被用于 await 语句。但是这种对象如果用上面的 isinstance 判断会返回 False。可以使用`inspect.isawaitable()`判断。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1509 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:46 · PVG 00:46 · LAX 08:46 · JFK 11:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.