asyncio
作者:互联网
asyncio还是一个python的单进程单线程程序,比较适合处理那些需要等待的任务。比如网络通信。
async的核心是一个事件循环event loop。event loop控制着任务的调度运行。同时执行的任务只有一个不存在系统级上下文切换和线程不一样。需要每个task告知event loop 运行完成可以让其他task运行。不存在竞争冒险问题,可以名确知道每个task什么时候停止运算。
coroutine
- coroutine function:由async修饰的函数
async def func():
pass
- coroutine object: 调用coroutine function的返回结果,但不会运行coroutine function里面的代码。
要想运行coroutine代码,需要进入事件循环,然后把coroutine转换成task
asyncio.run(coroutine object)
- asyncio.run接收一个coroutine object作为参数,建立一个事件循环,把coroutine object转换成一个task并注册到建立的事件循环中。事件循环建立后就会寻找可以运行的task,然后运行coroutine代码
- 不能在 asyncio.run 方法内部中再次调用 asyncio.run 方法,此方法在异步代码中只能被调用一次,否则会抛出 RuntimeError 异常;
- asyncio.run 只能执行 async 函数,不能执行普通函数(普通函数需要包装);
- asyncio.run 是阻塞运行的,直到执行的协程完成后才返回
import asyncio
async def coru_f(i):
await asyncio.sleep(1)
return i
async def coroutine_function(index):
print(f"coroutine {index} start")
var = await coru_f(index)
# await把coroutine object转换为一个新的task,并向event loop注册这个task
# 并告诉event loop 需要等待后面的新的task运行完才会继续运行当前task
# 然后在当前task等待新task运行完成时,event loop 会运行其他task
# 当event loop再次调度运行这个task值时,会获取新的task的返回值
# 并将其赋值给var
print(var)
print(f"exit coroutine {index}")
async def main():
await coroutine_function(1)
await coroutine_function(2)
if __name__ == "__main__":
coroutine_obj = main()
# 创建event loop,把coroutine object转换成task,然后运行task
asyncio.run(coroutine_obj) # asyncio.run是串行执行
asyncio.creat_task
asyncio.run和await只能串行执行,asyncio.creat_task同样接收一个coroutine object,会把coroutine object 转换为一个task,返回这个task并且向event loop注册这个task
import asyncio
import time
async def cor_fun(delay, string, index):
print(f"task{index} started at {time.strftime('%X')}")
await asyncio.sleep(delay) # 告诉event loop需要等待asyncio.sleep(delay) 运行完成,控制权交回给event loop, event loop就会调度其他task运行
print(string)
print(f"task{index} finished at {time.strftime('%X')}\n")
async def main():
task1 = asyncio.create_task(
cor_fun(1, "hello", 1)
) # 创建task并不会把控制权交回给event loop,所以不会调度运行新建的task,会继续运行main这个coroutine function的代码
task2 = asyncio.create_task(
cor_fun(2, "world", 2)
)
print(f"started at {time.strftime('%X')}\n")
await task1 # 告诉event loop需要等待task1 运行完成,控制权交回给event loop, event loop就会调度其他task运行
await task2
print(f"finished at {time.strftime('%X')}\n")
asyncio.run(main())
# started at 23:52:09
# task1 started at 23:52:09
# task2 started at 23:52:09
# hello
# task1 finished at 23:52:10
# world
# task2 finished at 23:52:11
# finished at 23:52:11
asyncio.gather
asyncio.gather接收多个task或coroutine或future,把多个task组合起来,返回一个future对象
import asyncio
import time
from pyrsistent import m
async def sum_(n):
print(f"calculate 1**3+.....+{n}**3 at {time.strftime('%X')}")
await asyncio.sleep(n//3)
ans = sum([i**3 for i in range(1,n+1)])
print(f"finished calculating 1**3+.....+n**3 at {time.strftime('%X')}")
return ans
async def main():
print(f"started at {time.strftime('%X')}")
res = await asyncio.gather(
sum_(5),
sum_(10),
sum_(3)
)
# future对象也可以await,await futer 告诉event loop 需要等待里面每一个task运行完成
# 同时把所有task的返回值放到一个list中返回
print(res)
print(f"finished at {time.strftime('%X')}")
if __name__ == "__main__":
asyncio.run(main())
# started at 00:08:12
# calculate 1**3+.....+n**3 at 00:08:12
# calculate 1**3+.....+n**3 at 00:08:12
# calculate 1**3+.....+n**3 at 00:08:12
# finished calculating 1**3+.....+n**3 at 00:08:13
# finished calculating 1**3+.....+n**3 at 00:08:13
# finished calculating 1**3+.....+n**3 at 00:08:15
# [225, 3025, 36]
# finished at 00:08:15
标签:task,coroutine,print,event,loop,asyncio 来源: https://www.cnblogs.com/baiyutang7/p/16410585.html