python协程实战
协程简介
协程(Coroutine)又称微线程、纤程,协程不是进程或线程,其执行过程类似于 Python 函数调用,Python 的 asyncio 模块实现的异步IO编程框架中,协程是对使用 async 关键字定义的异步函数的调用;
一个进程包含多个线程,类似于一个人体组织有多种细胞在工作,同样,一个程序可以包含多个协程。多个线程相对独立,线程的切换受系统控制。同样,多个协程也相对独立,但是其切换由程序自己控制。
一个简单例子
我们来使用一个简单的例子了解协程,首先看看下面的代码:
import time
def display(num):time.sleep(1)print(num)
for num in range(10):display(num)

很容易看得懂,程序会输出0到9的数字,每隔1秒中输出一个数字,因此整个程序的执行需要大约10秒 时间。值得注意的是,因为没有使用多线程或多进程(并发),程序中只有一个执行单元(只有一个线程在 执行),而 time.sleep(1) 的休眠操作会让整个线程停滞1秒钟,
对于上面的代码来说,在这段时间里面 CPU是闲置的没有做什么事情。
我们再来看看使用协程会发生什么:
import asyncio
async def display(num): # 在函数前使用async关键字,变成异步函数 await asyncio.sleep(1)print(num)

异步函数不同于普通函数,调用普通函数会得到返回值,而调用异步函数会得到一个协程对象。我们需要将协程对象放到一个事件循环中才能达到与其他协程对象协作的效果,因为事件循环会负责处理子程 序切换的操作。
简单的说就是让阻塞的子程序让出CPU给可以执行的子程序。

基本概念
异步IO是指程序发起一个IO操作(阻塞等待)后,不用等IO操作结束,可以继续其它操作;做其他事情,当IO操作结束时,会得到通知,然后继续执行。异步IO编程是实现并发的一种方式,适用于IO密集型任务
Python 模块 asyncio 提供了一个异步编程框架,全局的流程图大致如下:

代码介绍
import asyncioasync def test():await asyncio.sleep(1)print('hello 异步')c = test() # 调用异步函数,得到协程对象-->c
loop = asyncio.get_event_loop() # 创建事件循环
loop.run_until_complete(c) # 把协程对象丢给循环,并执行异步函数内部代码
await asyncio.sleep(1):用来模拟耗时的任务
task:对协程对象的进一步封装
async def test():print('hello 异步')
c = test() # 调用异步函数,得到协程对象-->c
loop = asyncio.get_event_loop() # 创建事件循环
task = loop.create_task(c) # 创建task任务
print(task)
loop.run_until_complete(task) # 执行任务
future:代表以后执行或者没有执行的任务,实际上和task没有本质区别
async def func(url):print(f'正在对{url}发起请求:')print(f'请求{url}成功!')c = func('www.baidu.com') # 函数调用的写成对象--> cloop = asyncio.get_event_loop() # 创建一个事件循环对象
future_task = asyncio.ensure_future(c)
print(future_task, '未执行')
loop.run_until_complete(future_task) # 注册加启动
print(future_task, '执行完了')
多任务协程
任务(Task)对象用于封装协程对象,保存了协程运行后的状态,使用 run_until_complete() 方法将任务注册到事件循环;
如果我们想要使用多任务,那么我们就需要同时注册多个任务的列表,可以使用 run_until_complete(asyncio.wait(tasks)),
这里的tasks,表示一个任务序列(通常为列表)
注册多个任务也可以使用run_until_complete(asyncio. gather(*tasks))
import asyncio, timeasync def do_some_work(i, n): # 使用async关键字定义异步函数print('任务{}等待: {}秒'.format(i, n))await asyncio.sleep(n) # 休眠一段时间return '任务{}在{}秒后返回结束运行'.format(i, n)start_time = time.time() # 开始时间
tasks = [asyncio.ensure_future(do_some_work(1, 2)),asyncio.ensure_future(do_some_work(2, 1)),asyncio.ensure_future(do_some_work(3, 3))]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
for task in tasks:print('任务执行结果: ', task.result())
print('运行时间: ', time.time() - start_time)
以上就是协程的基本使用方法,下面做一个实战熟悉一下效果
协程实战
# -*- coding: utf-8 -*-
# Created by Xue Jian on 4/22/23
import asyncio
import os
import timeimport requests
import jsondef get_pages(limit=21):page_urls = []for i in range(1, limit):url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js'.format(i)# print(url)page_urls.append(url)return page_urlsheaders = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}def get_img(limit):img_urls = []page_urls = get_pages(limit=limit)for page_url in page_urls:res = requests.get(page_url, headers=headers)result = res.content.decode('utf-8')res_dict = json.loads(result)skins = res_dict['skins']img_url = []for hero in skins:# todo 这里item放在外面,只有最后一个结果item = {}item['name'] = hero["heroName"]item['skin_name'] = hero["name"]if hero["mainImg"] == '':continueitem['imgLink'] = hero["mainImg"]# print(item)img_url.append(item)img_urls.extend(img_url)return img_urls'''
{'name': '黑暗之女', 'skin_name': '毒菇梦魇 安妮', 'imgLink': 'https://game.gtimg.cn/images/lol/act/img/skin/big_4c8b9ce8-4d3f-4c05-80b9-3207891f0147.jpg'}
'''async def save_img(index, img_url):"""声明异步协程任务:param index::param img_url::return:"""path = "皮肤/" + img_url['name']if not os.path.exists(path):os.makedirs(path)content = requests.get(img_url['imgLink'], headers=headers).content# 这里就是会发生阻塞的任务 => await asyncio.sleep()print('******正在下载第{}张************'.format(index))with open('./皮肤/' + img_url['name'] + '/' + img_url['skin_name'] + str(index) + '.jpg', 'wb') as f:f.write(content)def main(limit):# 创建事件循环loop = asyncio.get_event_loop()# 获取图片url列表img_urls = get_img(limit)print(len(img_urls))# 创建协程任务tasks = [save_img(img[0], img[1]) for img in enumerate(img_urls)]try:loop.run_until_complete(asyncio.wait(tasks))finally:loop.close()"""以下是同步操作首先将 async def save_img(index, img) 改成 def save_img(index, img)将try finally替换成以下for index, img in enumerate(img_urls):save_img(index, img)"""if __name__ == '__main__':start = time.time()main(21)end = time.time()print('cost_timer:::', end - start)
相关文章:
python协程实战
协程简介 协程(Coroutine)又称微线程、纤程,协程不是进程或线程,其执行过程类似于 Python 函数调用,Python 的 asyncio 模块实现的异步IO编程框架中,协程是对使用 async 关键字定义的异步函数的调用; 一个进程包含多个线程,类似…...
【论文笔记】VideoGPT: Video Generation using VQ-VAE and Transformers
论文标题:VideoGPT: Video Generation using VQ-VAE and Transformers 论文代码:https://wilson1yan. github.io/videogpt/index.html. 论文链接:https://arxiv.org/abs/2104.10157 发表时间: 2021年9月 Abstract 作者提出了…...
scala之基础面向对象
scala 既是面向对象 也是函数式编程 从Java 发展而来,依赖JVM环境 一、 scala 在linux中运行 scala 模式中直接编写运行 scala文件,load执行 scala编译程序 编译 运行 scala java 二、scala 数据类型 基础数据类型 val 不可变变量 函数式编程 …...
Qt5.12实战之多线程编程概念
1.为什么要使用多线程? a. 基于线程,同时处理多个任务,软件响应更灵敏 b.充分利用CPU的多核心功能增加应用运行效率 c.多线程在同一进程间使用共享通信更加高效 d.多个线程之间进行切换比多个进程之间进行切换,线程开销更少. 2.操作系统与进程关系 a. MS-DOS系统 属于单进程…...
格式化数据恢复怎么做?超实用的3种方法在这!
案例:格式化数据怎么恢复 【我的电脑前段时间中病毒了,无奈之下我只能将其格式化,但是很多重要的文件和图片之类的也一起被删除了,有什么方法可以恢复这些格式化的数据吗?非常着急!】 格式化数据恢复&…...
【Java|golang】1105. 填充书架---动态规划
给定一个数组 books ,其中 books[i] [thicknessi, heighti] 表示第 i 本书的厚度和高度。你也会得到一个整数 shelfWidth 。 按顺序 将这些书摆放到总宽度为 shelfWidth 的书架上。 先选几本书放在书架上(它们的厚度之和小于等于书架的宽度 shelfWidt…...
linux基础命令
linux基础命令 一、linux命令 熟悉账务linux命令对运维的好处是巨大的,只有熟悉了命令咱们在运维的操作上才能如鱼得水。 系统信息 arch #显示机器的处理器架构(1) uname -m #显示机器的处理器架构(2) uname -r #显示正在使用的内核版本 dmidecode -q …...
【三十天精通Vue 3】 第十八天 Vue 3的国际化详解
✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue 3 国际化概述1.1 国际化的概念1.2 国际化的作用1.3 V…...
02 - 学会提问
学会提问 一、引言 1.1 GPT简介 GPT(Generative Pre-trained Transformer)是一种基于Transformer架构的大型预训练语言模型。 凭借其强大的文本生成、理解和处理能力,GPT已在诸如自然语言处理、机器翻译、文本摘要等多个领域取得了显著的…...
Java经典的Main方法面试题
mian方法是做什么用的? main方法是Java程序的入口方法,JVM在运行的时候会首先查找main方法不用main方法如何运行一个类? 不行,没有main方法我们不能运行Java类 在Java7之前,你可以通过使用静态初始化运行Java类。但是&…...
世界大学电子电气工程TOP10,国内大学哪家强?
EE究竟是什么专业 ? 在中国,工程系中跟电相关的专业,一般都切分得非常细。有电子工程、电气工程、通信工程、信息工程、自动化、测控仪器等。但在国外,一般把这些领域都归类到 Electrical Engineering 中,也就是我们常说的EE。 …...
5.3 牛顿-科茨公式
学习目标: 理解微积分基础知识,例如导数和微分的概念。学习牛顿-科茨公式的推导过程。这个公式实际上是使用泰勒公式对被积函数进行展开,并使用微积分的基本原理进行简化得到的。学习如何使用牛顿-科茨公式进行数值积分。这通常涉及到将被积…...
全注解下的SpringIoc 续2-bean的生命周期
spring中bean的生命周期 上一个小节梳理了一下Spring Boot的依赖注入的基本知识,今天来梳理一下spring中bean的生命周期。 下面,让我们一起看看bean在IOC容器中是怎么被创建和销毁的。 bean的生命周期大致分为四个部分: #mermaid-svg-GFXNEU…...
【VQ-VAE代码实战】Neural Discrete Representation Learning
【VQ-VAE代码实战】Neural Discrete Representation Learning 0、前言1、简介2、Basic IdeaLoss3、代码Load DataVector Quantizer LayerEncoder & Decoder ArchitectureTrainPlot LossView ReconstructionsView EmbeddingReference0、前言 论文地址:基于神经网络的,离散…...
gpt3.5和gpt4区别-gpt3.5和gpt4
gpt系列 GPT系列是OpenAI公司开发的一组基于人工智能深度学习技术的自然语言处理模型。GPT代表Generative Pre-trained Transformer,即预训练生成模型。目前,GPT模型已经推出了三代(GPT-1,GPT-2,GPT-3)&am…...
java获取当前系统时间
在Java中,可以使用以下几种方法获取当前系统时间: 方法1:使用java.util.Date类 java import java.util.Date; public class Main { public static void main(String[] args) { Date date new Date(); System.out.println("当前时间&…...
pbootcms自动配图出图插件
pbootcms文章无图自动出图配图插件的优点 1、提高文章的可读性和吸引力:插入图片可以丰富文章的内容和形式,增强读者的阅读体验和吸引力,提高文章的点击率和转化率。 2、节省时间和精力:手动添加图片需要花费大量时间和精力去寻找…...
手动测试台架搭建,让你的车载测试更轻松
目录:导读 引言 1、概述 2、主要内容 3、汽车测试台架分类 4、汽车测试台架分类 5、汽车测试台架分类台架测试输人台架硬件搭建CANoe台架搭建 6、台架测试输入? 7、需求规范是功能测试用例设计来源测试结果的判断﹔包括∶客户需求(功能规范)需求分…...
分组双轴图:揭示数据中的关联性和趋势变化
简介 分组双轴图是一种数据可视化图表,指有多个(≥2)Y轴的数据图表,多为分组柱状图折线图的结合,图表显示更为直观,可以很好地展示不同指标之间的关系,帮助用户更好地理解数据,做出…...
MATLAB函数封装1:生成QT可以调用的.dll动态链接库
在进行相关算法的开发和设计过程中,MATLAB具有特别的优势,尤其是对于矩阵运算的处理,具有很多现成的方法和函数可以进行调用,同时MATLAB支持把函数封装成不同的语言方便完成算法的集成。 这里记录利用MATLAB封装成C动态链接库&…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
