python初始异步编程第二节

"""
python异步携程编程
什么是协程?
    1、携程是可以暂停运行 也可以恢复执行的函数,通过async def 定义,
    他和普通函数不一样的地方是,它在执行时不会真的执行里面的代码
    而是返回一个协程对象,在执行协程对象时 才会执行里面的代码,
    2、当出现await时,协程会暂停运行,让出控制权,
    等await完成了在请求控制权恢复运行
    3、拥有控制权的协程能运行,没有控制权的协程只能等待
什么是事件循环?
     事件循环主要做几件事如下:
     1、第一步 检查携程,拿到控制权后检查有没有可以执行的协程
     2、第二步 让出控制,将控制权传递给可以执行的协程
     3、第三步 等待协程,等当前协程暂停或者运行完,放开控制权给自己,然后在回到第一步
     问题:事件循环怎么能知道哪些协程可以执行,哪些协程不可以执行呢?
     答: 通过任务,任务是对协程的封装,除了包含协程本身还记录了协程的状态,
     例如准备执行,正在运行,已完成等等
     让事件循环知道,当前协程能不能够执行,只要一个协程被包装成任务了,
     他就会被事件循环调度执行

什么是任务?
     任务是包含协程的task,创建任务有两种方式
     1、手动创建任务,适合可以在中途对任务做一些其他的操作
       task=asyncio.create_task( 协程函数() )

     2、自动创建任务并返回结果,不需要对任务中途进行处理的场景,
        2.1 实现方式一
         如下可以一起执行多个协程函数,当所有协程函数都执行完了,
         就返回结果列表,结果获取的顺序和传入顺序是一样的
         asyncio.gather(协程函数1(),协程函数2(),协程函数3())
         通过await来等待获取结果列表,并获取到结果
         result= await  asyncio.gather(协程函数1(),协程函数2(),协程函数3())
        2.2 实现方式二
         as_completed 的输入参数是 包含协程的可迭代对象
        返回参数是一个迭代器,迭代器会按照协程完成的顺序依次返回已完成的协程
         results=asyncio.as_completed([协程函数1(),协程函数2()])
         使用await可以返回已完成的协程结果
         for result in results:
             print(await result)
        2.3 区别:asyncio.gather,与asyncio.as_completed区别是
         前者gather是把所有协程都执行完再返回结果列表
         后者as_completed是执行完了一个协程结果就返回一个
    使用建议:
       如果你想执行完了立即处理结果 as_completed会更适合你



await关键字?
    1、await关键字是让出当前协程控制权,暂停当前携程执行,
    2、await关键字只能出现在协程函数中,非协程函数无法使用,
    必须是async def 的函数

三、案例  异步执行  模拟 网络读取文件,解析文件两个函数
    1、定义协程函数,async def 、在函数内需要暂停的地方可以使用await,
    但是要注意 await暂停后面的代码也要执行 需要使用协程 例如asyncio.sleep(1)

    2、把协程包装成任务
    task1=asyncio.create_task( 协程函数() )
    3、建立事件循环
    把任务交给事件循环管理
    asyncio.run(task1)
"""
import asyncio
from time import perf_counter


#定义协程函数  在需要暂停的地方
async def fetch_url(url):#请求url 模拟网络请求
    print("开始执行 fetch_url")

    # 使用await暂停当前携程,等sleep完成了在来执行
    # 但是让谁来执行sleep呢?答案是让协程来执行所以使用asyncio.
    # 所以我们把 sleep 修改为 asyncio.sleep
    # 一会我们还会把 函数包装成任务
    # 因为只有把协程包装成任务了 才能让事件去执行监听
    await asyncio.sleep(1)

    print("完成执行 fetch_url")
    return "url_content";
async def read_file(file_path):
    print("开始执行 read_file")

    # 使用await暂停当前携程,等sleep完成了在来执行
    # 但是让谁来执行sleep呢?答案是让协程来执行所以使用asyncio.
    # 所以我们把 sleep 修改为 asyncio.sleep
    # 一会我们还会把 函数包装成任务
    # 因为只有把协程包装成任务了 才能让事件去执行监听
    await asyncio.sleep(1)

    print("完成执行 read_file")
    return "file_content"
async def main():
    url="www.baidu.com"
    file_path="./test.txt"
    #把协程请求函数包装成任务
    task1=asyncio.create_task(fetch_url(url))
    #把协程读取文件函数包装成任务
    task2=asyncio.create_task(read_file(file_path))

    #获取到携程函数的返回值,使用await
    url_content=await task1
    file_content=await task2

    print(url_content)
    print(file_content)

if __name__ == '__main__':
    #记录开始时间
    start_time=perf_counter()
    #创建事件循环,把协程放入事件循环中
    asyncio.run(main())
    end_time=perf_counter()
    print("执行时间:",end_time-start_time)

 

posted @ 2025-03-22 14:41  郎小乐  阅读(27)  评论(0)    收藏  举报