锦通 发表于 2022-8-9 17:53:36

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:11asyncio.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()
    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
#
# finished at 00:08:15
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: asyncio