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

2017-06-15 15:54:57 +08:00
 ray1888

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 后面只能调用异步的函数吗?求大神解答

6672 次点击
所在节点    Python
11 条回复
kindjeff
2017-06-15 15:57:12 +08:00
是的
ray1888
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
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
2017-06-15 16:02:11 +08:00
去掉 11 行的 await
ray1888
2017-06-15 16:16:34 +08:00
@dishonest 其实就是想问 await 后面能接什么函数而已,如果打掉 11 行的 await,就相当于让渡之后拿到控制权的函数线性执行
mxi1
2017-06-15 16:20:32 +08:00
await 必须是 async 的方法吧,3.5 之前是通过 decorator 的方式实现的,你读读当时的文档,应该有介绍原理的
zhengxiaowai
2017-06-15 16:21:53 +08:00
跟 coroutine object
kindjeff
2017-06-15 16:21:57 +08:00
@ray1888 你写的几个函数就是应该让他们一直执行啊,IO 操作的时候你才应该用 await 把执行权给别的位置。await 后面应该接一个 awaitable 的东西。
ray1888
2017-06-15 16:32:31 +08:00
@kindjeff 所以是 await 函数接的是 IO 操作对应的函数?不是很懂
AX5N
2017-06-16 01:03:22 +08:00
“第二种就不会报错,那么 await 后面只能调用异步的函数吗?求大神解答”
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()`判断。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/368637

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX