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动态链接库&…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...

Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...