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


相关推荐

  • 小程序align-items和justify-content 对齐方式之不同

    小程序align-items和justify-content 对齐方式之不同

    2021年3月12日
    235
  • Java Jsoup 解析处理百度谷歌搜索结果的示例代码

    Java Jsoup 解析处理百度谷歌搜索结果的示例代码本文主要介绍Java中,通过Jsoup来解析百度和谷歌中的搜索结果,获取搜索到的链接url和标题title的方法,以及相关的示例代码。原文地址:JavaJsoup解析处理百度谷歌搜索结果的示例代码

    2022年6月15日
    47
  • 算法笔记–sg函数详解及其模板

    算法笔记–sg函数详解及其模板

    2022年3月5日
    48
  • 如何进行大数据处理?大数据处理的方法步骤[通俗易懂]

    如何进行大数据处理?大数据处理的方法步骤[通俗易懂]1.大数据处理之一:采集大数据的采集是指利用多个数据库来接收发自客户端(Web、App或者传感器形式等)的数据,并且用户可以通过这些数据库来进行简单的查询和处理工作。比如,电商会使用传统的关系型数据库MySQL和Oracle等来存储每一笔事务数据,除此之外,Redis和MongoDB这样的NoSQL数据库也常用于数据的采集。在大数据的采集过程中,其主要特点和挑战是并发数高,因为同时有…

    2022年5月16日
    75
  • flowable流程详解

    flowable流程详解flowable图例解释请假流程bpmn20.xml文件请假流程示例图例解释开始事件:图中用细线圆圈来表示,是流程实例的开始点箭头:表示节点之间的流转指向。用户任务:在图中用左上角有人的圆角矩形表示,这些是需要用户来操作的节点。图中有两个,第一个表示需要经理进行审批来同意或拒绝,第二个表示用户来确认销假。排它网关:用叉形符号填充的菱形表示,从该图中出来的箭头往往有多个,但只有一个满足条件,流程会沿着满足条件的方向流转。自动化任务:左上角有齿轮形状的的圆角矩形,表示自动执行的节点。图中

    2022年5月11日
    316
  • String.Split()函数

    String.Split()函数

    2021年11月13日
    52

发表回复

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

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