协程高并发 – asyncio异步

协程高并发 – asyncio异步aoao 快的协程

1 – 协程基础知识

2 – 执行协程函数中的代码

3 – 实现异步的正确方式

4 – 获取协程函数的返回值

5 – 协程的高并发实例

协程函数

 # 定义协程函数 async def func(): print("这是一个协程函数") 

协程对象

 # 定义协程函数 async def func(): print("这是一个协程函数") if __name__ == '__main__': # coro: 协程对象 # 此时 func函数 里面的代码 并不会像普通函数一样 被执行 coro = func() 

await关键字

 import asyncio """ await 只能在协程中使用 await + 可等待的对象 比如 await 协程对象/task对象/future对象 使用create_task方法 可以把协程对象 封装成task对象 官方建议使用task对象 """ async def job(): print("正在下载") await asyncio.sleep(1) # 协程中的睡眠 print("下载完成") async def run(): print("开始执行") await job() # 此处是 await 协程对象 await asyncio.create_task(job()) # 此处是 await task对象 await asyncio.ensure_future(job()) # 此处是 await future对象 print("执行完成") 

协程的顶层入口

 import asyncio # 定义协程函数 async def func(): print("这是一个协程函数") if __name__ == '__main__': # run方法: 协程的顶层入口 # 这样func函数中的代码就会执行 asyncio.run(func()) 

协程调用协程

import asyncio async def job(param): print("job执行了, 参数是", param) # 在协程中调用另一个协程 async def run(): # await 一个协程对象 就能执行这个协程 await job("python newbee") if __name__ == '__main__': asyncio.run(run()) 

运行结果

job执行了, 参数是 python newbee 

创建task对象

import asyncio async def job(param): print("job执行了, 参数是", param) # 在协程中调用另一个协程 async def run(): # 把协程对象 封装成 task对象 也能执行协程 asyncio.create_task(job("task对象")) if __name__ == '__main__': asyncio.run(run()) 

运行结果

job执行了, 参数是 task对象 

错误的调用写法

import asyncio import time async def job(a): print("正在下载 参数是", a, time.time()) print("下载完成 参数是", a, time.time()) print() await asyncio.sleep(1) # 使用了3次await async def run(): coro1 = job(1) await coro1 coro2 = job(2) await coro2 coro3 = job(3) await coro3 if __name__ == '__main__': t1 = time.time() asyncio.run(run()) print("耗时:", time.time() - t1) 

运行结果

很明显是同步效果,一个任务执行消耗1秒,三个就是3秒

正在下载 参数是 1 .2335 下载完成 参数是 1 .2335 正在下载 参数是 2 . 下载完成 参数是 2 . 正在下载 参数是 3 . 下载完成 参数是 3 . 耗时: 3.00457 

wait方法放在协程函数中

import asyncio import time async def job(a): print("正在下载 参数是", a, time.time()) print("下载完成 参数是", a, time.time()) print() await asyncio.sleep(1) # 用了1次await async def run(): coros = [job(a) for a in range(3)] await asyncio.wait(coros) if __name__ == '__main__': t1 = time.time() asyncio.run(run()) print("耗时:", time.time() - t1) 

运行结果

执行的时间戳一模一样,达到了真正的异步

正在下载 参数是 1 . 下载完成 参数是 1 . 正在下载 参数是 0 . 下载完成 参数是 0 . 正在下载 参数是 2 . 下载完成 参数是 2 . 耗时: 1.00017 

wait方法放在顶层入口

import asyncio import time async def job(a): print("正在下载 参数是", a, time.time()) print("下载完成 参数是", a, time.time()) print() await asyncio.sleep(1) if __name__ == '__main__': t1 = time.time() coros = [job(a) for a in range(3)] asyncio.run(asyncio.wait(coros)) print("耗时:", time.time() - t1) 

运行结果

执行的时间戳一模一样,达到了真正的异步

正在下载 参数是 1 . 下载完成 参数是 1 . 正在下载 参数是 2 . 下载完成 参数是 2 . 正在下载 参数是 0 . 下载完成 参数是 0 . 耗时: 1.00654 

使用回调函数

import asyncio from functools import partial # 回调函数 def callback(task): print("返回的结果是: ", task.result()) async def job(): print("job执行了") print("job结束了") return 100 async def run(): task = asyncio.create_task(job()) # 协程任务完成后, 回调函数才会执行  task.add_done_callback(partial(callback)) if __name__ == '__main__': asyncio.run(run()) 

运行结果

job执行了 job结束了 返回的结果是: 100 




最简单的接收

import asyncio async def job(param): print("job执行了, 参数是", param) return 100 async def run(): result1 = await job("coroutine") print(result1) result2 = await asyncio.create_task(job("task")) print(result2) if __name__ == '__main__': asyncio.run(run()) 

运行结果

job执行了, 参数是 coroutine 100 job执行了, 参数是 task 100 

使用wait方法

 import asyncio import time ''' wait方法会自动将协程对象 封装成task对象进行处理 wait方法在内部用set保存 它创建的task对象 因为set是无序的, 所以任务不是顺序执行 ''' now = lambda: time.time() async def func(idx): print(f"func执行了, 参数: { 
                                    idx}, 时间戳: { 
                                    now()}") await asyncio.sleep(1) return 100 async def run1(): tasks = [asyncio.create_task(func(idx)) for idx in range(10)] # 等待返回结果 await asyncio.wait(tasks) # 获取返回值 for task in tasks: print(task.result()) async def run2(): coros = [func(a) for a in range(10)] # wait方法会自动 把coros中的协程对象 封装成task对象 # wait方法返回一个元组, 元组中有两个集合 # done: 已经完成任务的task对象集合 # pending: 未完成任务的task对象集合 # 调用task对象的result方法可以获取 协程的返回结果 done, pending = await asyncio.wait(coros) for task in done: print(tasks.result()) if __name__ == '__main__': # 执行协程 asyncio.run(run1()) 

使用gather方法

 import asyncio import time ''' gather方法的任务是顺序执行的 ''' now = lambda: time.time() async def func(idx): print(f"func执行了, 参数: { 
                                       idx}, 时间戳: { 
                                       now()}") return 100 async def run1(): tasks = [asyncio.create_task(func(idx)) for idx in range(10)] # 等待返回结果 await asyncio.gather(*tasks) # 获取返回值 for task in tasks: print(task.result()) async def run2(): # 把多个协程对象装到一个列表中 coros = [func(a) for a in range(10)] # gather方法返回一个列表 # 列表中的每一个元素就是协程的返回结果 results = await asyncio.gather(*coros) for result in results: print(result) if __name__ == '__main__': # 执行协程 asyncio.run(run1()) 

使用as_completed方法

import asyncio from random import randint async def job(delay): print("开始下载", delay) await asyncio.sleep(delay) print("下载完成", delay) return delay async def use_as_completed(): tasks = [ asyncio.create_task(job(randint(1, 3))) for _ in range(6) ] # 使用as_completed方法的好处 # 任务先完成就立即返回, 而不是等待所有任务完成后再一起返回 for coro in asyncio.as_completed(tasks): result = await coro print("返回:", result) print("上面使用as_completed") async def use_wait(): tasks = [ asyncio.create_task(job(randint(1, 3))) for _ in range(6) ] # 使用wait方法 # 单个任务执行完了, 也要等待所有任务完成后, 再一起返回 done, pending = await asyncio.wait(tasks) for task in done: print("返回:", task.result()) print("上面使用wait") if __name__ == '__main__': asyncio.run(use_wait()) print() asyncio.run(use_as_completed()) 

运行结果

开始下载 1 开始下载 2 开始下载 1 开始下载 3 开始下载 3 开始下载 3 下载完成 1 下载完成 1 下载完成 2 下载完成 3 下载完成 3 下载完成 3 返回: 3 返回: 1 返回: 3 返回: 1 返回: 3 返回: 2 上面使用wait 开始下载 1 开始下载 3 开始下载 3 开始下载 2 开始下载 3 开始下载 1 下载完成 1 下载完成 1 返回: 1 返回: 1 下载完成 2 返回: 2 下载完成 3 下载完成 3 下载完成 3 返回: 3 返回: 3 返回: 3 上面使用as_completed 




执行5000个相同的协程

 import asyncio import time """ 一共有5000个 parse_detail 执行 """ # 返回时间戳, 方便记录 程序执行完毕 所消耗的时间 now = lambda: time.time() # 解析详情页 async def parse_detail(id): print(f"正在解析 详情页{ 
                                          id} --> { 
                                          now()}") await asyncio.sleep(1) # 睡眠1秒 print(f"详情页{ 
                                          id} 解析完成 --> { 
                                          now()}") # 解析列表页 async def parse_page(page): print(f"正在解析 列表页{ 
                                          page} --> { 
                                          now()}") # 内层的任务列表 # 每一个页面有1000个详情页 detail_coros = [ parse_detail(f"{ 
                                          page}/{ 
                                          id}") for id in range(1, 1001) ] await asyncio.wait(detail_coros) print(f"列表页{ 
                                          page} 解析完成 --> { 
                                          now()}") async def run(): # 外层的任务列表 # 构造了5个列表页 page_coros = [ parse_page(page) for page in range(1, 6) ] await asyncio.wait(page_coros) if __name__ == '__main__': t1 = now() asyncio.run(run()) print(f"耗时: { 
                                          now() - t1}") 







































版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233649.html原文链接:https://javaforall.net

(0)
上一篇 2025年7月2日 下午1:01
下一篇 2025年7月2日 下午1:22


相关推荐

  • Java动态数组

    Java动态数组1 Java 动态数组的用法详解 nbsp nbsp nbsp Java 动态数组是一种可以任意伸缩数组长度的对象 在 Java 中比较常用的是 ArrayList ArrayList 是 javaAPI 中自带的 java util ArrayList 下面介绍一下 ArrayList 作为 Java 动态数组的用法 nbsp 语法 add 是添加一个新的元素 remove 删除一个元素 size 获得 ArrayList 的长度 ArrayL

    2026年3月16日
    1
  • int转long Long型

    int转long Long型Longl=(Long)5;以上的不行 因为Long是包装类,而int是值类型数据,两者是不能这样强转的。longl=(long)5; int和long都是基本类型的数据,是可以强转的,那么我就可以以此作为桥梁,强转成long后,再生成Long类型的数据。Longl=newLong((long)5); 这样就可以将int类型顺利转换为Long…

    2022年5月3日
    84
  • Charles抓包神器

    Charles抓包神器Charles抓包神器Charles抓包过程插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML图表FLowchart流程图导出与导入导出导入Charles是一个HTTP代理服务器,HTTP监视器,反转代理服务器,当程序连接…

    2022年6月3日
    39
  • AnalyticDB for MySQL 3.0 技术架构解析

    AnalyticDB for MySQL 3.0 技术架构解析企业数据需求不断变化,近年来变化趋势日益明显,从数据的3V特性看:体积,速度和变化;BigData强调数据量,PB级以上,是静态数据。而FastData在数据量的基础上,意味着速度和和变化,意味着客户可以更加实时化、更加快速地进行数据处理。在Forrester最近的一项研究中,超过75%的…

    2025年12月12日
    5
  • ComfyUI 便宜的GPT Image和Flux、Flux Kontext插件

    ComfyUI 便宜的GPT Image和Flux、Flux Kontext插件

    2026年3月16日
    2
  • 腾讯云轻量服务器+OpenClaw快速打造企业智能对话中枢

    腾讯云轻量服务器+OpenClaw快速打造企业智能对话中枢

    2026年3月13日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号