协程高并发 – 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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ip地址是什么意思_手机ip显示归属地还是显示本地

    ip地址是什么意思_手机ip显示归属地还是显示本地如何通过IP找到地址?在我们印象中,我们都知道可以通过IP地址找到某个人。但当我们细想一下,我们会发现其实IP地址与地理位置并不是直接相关的。那我们到底是如何通过IP地址找到地址的呢?答案是:通过自治系统(AutonomousSystem)。互联网是由不同网络组成的网络,自治系统是组成Internet的大型网络,连接到Internet的每台计算机或设备都连接到一个AS。而每一个自治系统都会有一个编码,我们称之为ASN。…

    2025年11月16日
    4
  • 逆向工程入门「建议收藏」

    逆向工程入门「建议收藏」本问只是为初入逆向工程大坑的新人们指出方向学习,没有实质性的技术。总的来说,基础才是最重要的。逆向工程入门应该算是所有学习方向中最难的。但是选择了这一方向的请不要放弃,一旦学成,必定会是大神级别的存在。那么,逆向工程的入门需要学习什么?1.c语言学习c语言是逆向工程的基础。如果是学习渗透方向的,也许可以选择python作为自己的第一门编程语言。但是作为逆向工程方向,第一门入门的语言没有选择,只有

    2022年6月19日
    65
  • 毕设代做正规平台_毕设代做被发现会不毕业吗

    毕设代做正规平台_毕设代做被发现会不毕业吗在mac自建一套【学员管理系统】

    2026年2月3日
    27
  • TP50 TP90 TP99 TP999 详细说明

    TP50 TP90 TP99 TP999 详细说明本文是根据自己的总结和网络总结得出 1 TP 指标说明 TP 指标 指在一个时间段内 统计该方法每次调用所消耗的时间 并将这些时间按从小到大的顺序进行排序 并取出结果为 总次数 指标数 对应 TP 指标的值 在取出排序好的时间 TP50 TP90 TP99 TP999 计算方式一致 TP90 TP99 TP999 则对方法性能要求很高 2 国外资料 在参考文章中的

    2025年10月21日
    4
  • Spring Boot 项目最优雅的 HTTP 客户端工具,用它就够了,太香了!

    大家都知道okhttp是一款由square公司开源的java版本http客户端工具。实际上,square公司还开源了基于okhttp进一步封装的retrofit工具,用来支持通过接…

    2021年6月22日
    132
  • navicat破解激活码2022【中文破解版】

    (navicat破解激活码2022)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~4K…

    2022年4月1日
    221

发表回复

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

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