python3.8:异步 asyncio 执行顺序

先看几种协程的执行情况:

1、 协程函数中没有 await,即没有可等待对象。且 调用函数 main() 也是直接用 await 调用,即不先创建 task。

import asyncio
import time

async def first_fun(delay):
    print('开始执行 first_fun 函数。')
    # await asyncio.sleep(delay)        # 注释掉,使其没有可等待对象。
    print('first_fun 函数执行结束。')
    return delay

async def second_fun(delay):
    print('开始执行 second_fun 函数。')
    # await asyncio.sleep(delay)
    print('second_fun 函数执行结束。')
    return delay

async def main():    
    print(f"started at {time.strftime('%X')}")

    await first_fun(2)      # ⑴
    await second_fun(3)		# ⑵

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

执行结果为:

started at 19:21:49
开始执行 first_fun 函数。
first_fun 函数执行结束。
开始执行 second_fun 函数。
second_fun 函数执行结束。
finished at 19:21:49

说明执行顺序就是 从上到下的执行顺序,即当代码运行到 (1)处时,它会先把(1)引用的函数运行结束,才会再运行(2),和普通函数调用效果一样。
 

2、 协程函数中加入可等待对象,这里用 asyncio.sleep()进行模拟。

import asyncio
import time

async def first_fun(delay):
    print('开始执行 first_fun 函数。')
    await asyncio.sleep(delay)
    print('first_fun 函数执行结束。')
    return delay

async def second_fun(delay):
    print('开始执行 second_fun 函数。')
    await asyncio.sleep(delay)
    print('second_fun 函数执行结束。')
    return delay

async def main():
    print(f"started at {time.strftime('%X')}")

    await first_fun(2)
    await second_fun(3)

    # first = asyncio.create_task(first_fun(2))
    # second = asyncio.create_task(second_fun(3))

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

执行结果为:

started at 19:29:04
开始执行 first_fun 函数。
first_fun 函数执行结束。
开始执行 second_fun 函数。
second_fun 函数执行结束。
finished at 19:29:09

可以看出,执行顺序和普通函数也没区别。执行时间,就是两个协程函数的总和。
说明:main() 函数中直接用 await 调用协程函数,就是普通的函数调用。


3、 main() 函数中创建task(), 但调用的协程函数中没有 await 可等待对象。main 中也没有用 await 来引用 task。

import asyncio
import time

async def first_fun(delay):
    print('开始执行 first_fun 函数。')
    # await asyncio.sleep(delay)      # 注释掉,使其没有可等待对象。
    print('first_fun 函数执行结束。')
    return delay

async def second_fun(delay):
    print('开始执行 second_fun 函数。')
    # await asyncio.sleep(delay)
    print('second_fun 函数执行结束。')
    return delay

async def main():
    print(f"started at {time.strftime('%X')}")

    first = asyncio.create_task(first_fun(2))      # ⑴
    print('=============')
    second = asyncio.create_task(second_fun(3))    # ⑵

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

执行结果为:

started at 19:40:34
=============
finished at 19:40:34
开始执行 first_fun 函数。
first_fun 函数执行结束。
开始执行 second_fun 函数。
second_fun 函数执行结束。

说明:代码运行到 ⑴ 处,它就会开辟一个“协程分支”,被调用的 first_fun(2) 会进入那个“分支”运行,然后马上运行下面的代码,不会影响 “主协程” 的运行脚步。


4、 main() 函数中创建task(), 调用的协程函数中有 await 可等待对象。 但 main 中也没有用 await 来引用 task。

import asyncio
import time

async def first_fun(delay):
    print('开始执行 first_fun 函数。')
    await asyncio.sleep(delay)          # 加入模拟的可等待对象。
    print('first_fun 函数执行结束。')
    return delay

async def second_fun(delay):
    print('开始执行 second_fun 函数。')
    await asyncio.sleep(delay)
    print('second_fun 函数执行结束。')
    return delay

async def main():
    print(f"started at {time.strftime('%X')}")

    first = asyncio.create_task(first_fun(2))
    print('=============')
    second = asyncio.create_task(second_fun(3))


    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

执行结果为:

started at 19:56:24
=============
finished at 19:56:24
开始执行 first_fun 函数。
开始执行 second_fun 函数。

从结果中看出,协程分支中有了可等待对象,但因为main函数中没有用 await来引用 task,所以就获取不到协程分支中 等待 运行之后的结果了。 因为 还没还没等到支协程返回结果,主线程已经结束了。


5、 main() 函数中创建task(), 但调用的协程函数中有 await 可等待对象。 main 中,只用 await 来引用 了一个task,等待2秒的那个 first。

import asyncio
import time

async def first_fun(delay):
    print('开始执行 first_fun 函数。')
    await asyncio.sleep(delay)
    print('first_fun 函数执行结束。')
    return delay

async def second_fun(delay):
    print('开始执行 second_fun 函数。')
    await asyncio.sleep(delay)
    print('second_fun 函数执行结束。')
    return delay

async def main():
    print(f"started at {time.strftime('%X')}")

    first = asyncio.create_task(first_fun(2))
    print('=============')
    second = asyncio.create_task(second_fun(3))
    
    await first      # ⑴

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

运行结果为:

started at 20:10:00
=============
开始执行 first_fun 函数。
开始执行 second_fun 函数。
first_fun 函数执行结束。
finished at 20:10:02

此时 代码 ⑴ 的 await 在等待接收 first_fun 协程运行结束, 但没有等待 second_fun,所以 还没运行到 second_fun 函数执行结束,主线程已经结束了。

6、 main() 函数中创建task(), 但调用的协程函数中有 await 可等待对象。 main 中,只用 await 来引用 了一个task,等待3秒的那个second。

import asyncio
import time

async def first_fun(delay):
    print('开始执行 first_fun 函数。')
    await asyncio.sleep(delay)
    print('first_fun 函数执行结束。')
    return delay

async def second_fun(delay):
    print('开始执行 second_fun 函数。')
    await asyncio.sleep(delay)
    print('second_fun 函数执行结束。')
    return delay

async def main():
    print(f"started at {time.strftime('%X')}")

    first = asyncio.create_task(first_fun(2))
    print('=============')
    second = asyncio.create_task(second_fun(3))

    # await first    # ⑴
    await second


    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

运行结果为:

started at 20:18:02
=============
开始执行 first_fun 函数。
开始执行 second_fun 函数。
first_fun 函数执行结束。
second_fun 函数执行结束。
finished at 20:18:05

此时获得的是完整的运行结果。因为这次 await 是等待 second 的运行结束。当等待3秒的second结束时,等待2秒的first已经提前结束了。所以此时 如果代码 ⑴ 即使不注释掉,运行结果也是一样的。

最后总结:
main()函数中:
asyncio.create_task():就相当于开启了一个线程。
await :        相当用线程的 join,等待协程的运行结束,再继续运行之后的代码。

如果协程最后有 return 的返回值,可以这样获取返回值:

async def main():
    print(f"started at {time.strftime('%X')}")

    first = asyncio.create_task(first_fun(2))
    second = asyncio.create_task(second_fun(3))

    await first
    s = await second    # 获取协程的返回值。
    print(s)

    print(f"finished at {time.strftime('%X')}")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值