Python协程的作用

        过分揣测别人的想法,就会失去自己的立场。大家好,当代软件开发领域中,异步编程已成为一种不可或缺的技术,用于处理大规模数据处理、高并发网络请求、实时通信等应用场景。而Python协程(Coroutine)作为一种高效的异步编程模型,引起了广泛的关注和应用。通过利用Python协程,开发者可以以更加简洁、可读性更高的方式编写异步代码,实现并发执行和非阻塞IO操作,从而提高程序的性能和响应能力。

一、协程介绍

        协程(Coroutines)是一种轻量级的并发编程方式,可用于在单线程内实现并发和异步操作。Python 提供了协程的支持,通过 asyncio 模块和 async/await 关键字,可以编写异步代码并实现高效的非阻塞 IO 操作。

Python 协程相对于多线程具有以下几个优势:

  • 轻量级:协程是在单个线程内执行的,因此相比于多线程,协程的创建和切换开销较小,占用的系统资源更少。

  • 高效的并发:协程利用异步非阻塞的方式实现并发操作,可以在等待 IO 操作时挂起,让出 CPU 的执行权,从而充分利用 CPU 的处理能力。相比于多线程,协程在 IO 密集型任务中通常表现更好。

  • 简化的同步编程:使用协程和 async/await 关键字,可以编写类似于同步代码的异步代码。协程在编写和理解上更加直观和简单,避免了传统多线程编程中的锁和线程同步等问题。

  • 避免竞态条件:由于协程在单线程内运行,不存在多线程的竞态条件(Race Condition)问题。协程的执行是按顺序逐个执行的,不需要额外的同步机制来保证数据的一致性。

  • 可扩展性:协程模型可以方便地实现高层级的并发和并行操作。通过协程的组合和调度,可以构建复杂的并发模式,如并发任务的并行执行、协程间的消息传递等。

应用场景:

  • 异步网络编程:协程在网络编程中非常有用,特别是在处理大量并发连接的情况下。通过使用协程,可以实现高性能的异步网络服务器和客户端,处理并发的网络请求、响应和数据传输。

  • 异步 IO 操作:协程适用于处理各种异步 IO 操作,如文件读写、数据库查询、网络请求等。通过使用协程,可以避免阻塞主线程,提高程序的吞吐量和响应能力。

  • Web 开发框架:许多 Python Web 框架(如Tornado、Sanic、FastAPI等)使用协程作为并发处理请求的方式。这些框架利用协程的特性处理大量的并发请求,提供高性能的 Web 服务。

  • 数据爬取和抓取:协程在数据爬取和抓取任务中非常常见。通过使用协程,可以并发地发送请求、解析响应和提取数据,从而加快数据获取的速度。

  • 并发任务调度:协程可以用于并发任务的调度和执行。通过构建协程任务队列,并使用协程调度器进行任务的调度和执行,可以实现高效的并发任务处理。

  • 高性能计算:虽然协程主要用于处理 IO 密集型任务,但在某些情况下,也可以用于并发执行计算密集型任务。通过合理的任务调度和利用协程的非阻塞特性,可以充分利用 CPU 资源,提高计算任务的执行效率。

        Python 协程相对于多线程更加轻量且高效,适用于处理 IO 密集型任务和异步编程场景。它简化了异步编程的复杂性,并提供了一种更加直观和简单的方式来实现并发操作。然而,协程也有一些局限性,例如无法利用多核 CPU 的并行处理能力,因此在 CPU 密集型任务中可能不如多线程效果好。在实际应用中,需要根据具体的需求和场景选择适合的并发模型。

二、async 和 await 关键字

async 和 await 是 Python 3.5+ 引入的关键字,用于定义和管理协程(Coroutines)。

1、async 关键字

async 关键字用于修饰函数 ,将其标记为协程函数(coroutine function)。协程函数在调用时返回一个协程对象,并且可以包含 await 表达式。

协程函数的执行过程中,可以使用 await 等待其他协程对象的执行结果,同时挂起自身的执行,并将控制权交给事件循环(Event Loop)。

在协程函数内部,可以执行异步操作,如异步 IO、 网络请求等,而无需阻塞整个程序的执行。

async def my_coroutine():# 协程函数的逻辑await some_async_operation()# 其他操作

2、await 关键字

  • await 关键字用于等待一个协程对象的执行结果,并暂时挂起当前协程的执行,直到该协程执行完成并返回结果。
  • 在协程函数内部使用 await 关键字时,协程会将控制权交给事件循环,以便在等待期间执行其他协程或异步操作。
  • await 表达式通常用于异步操作的调用,如异步 IO 操作、网络请求等,以便在等待期间不阻塞程序的其他部分。
async def my_coroutine():# 协程函数的逻辑result = await some_async_operation()# 使用结果进行其他操作

        使用 async 和 await 关键字可以轻松地编写异步代码,实现协程的挂起和恢复,并在等待异步操作时不阻塞整个程序的执行。这种方式使得编写异步程序更加直观和简洁,类似于编写同步代码的方式。同时,通过事件循环的调度,协程可以高效地处理并发任务和异步操作,提高程序的性能和响应能力。

三、协程对象

        协程对象是使用 async 关键字定义的函数的返回结果。它代表一个暂停执行的函数,可以通过 await 等待其执行完成,并获得其返回值。

1、创建协程对象

  • 协程对象是通过调用使用 async 关键字定义的协程函数来创建的。协程函数在调用时不会立即执行函数体内的代码,而是返回一个协程对象。
  • 协程对象可以像普通函数一样被调用,但是它的执行需要通过事件循环(Event Loop)的调度来实现。
import asyncioasync def my_coroutine():# 协程逻辑await asyncio.sleep(1)return "Coroutine finished"coro = my_coroutine()  # 创建协程对象

2、等待协程对象的执行

  • 协程对象可以被等待和执行,以获取其执行结果。这通常通过在其他协程或异步函数内使用 await 关键字来实现。
  • 在等待协程对象时,当前的协程会暂时挂起,让出事件循环的控制权,等待协程对象的执行完成,并获得其返回值。
import asyncioasync def my_coroutine():# 协程逻辑await asyncio.sleep(1)return "Coroutine finished"async def main():result = await my_coroutine()  # 等待协程对象的执行print(result)loop = asyncio.get_event_loop()
loop.run_until_complete(main())

3、协程对象的状态

  • 协程对象有三种状态:等待状态(awaitable)、运行状态(running)和完成状态(done)。
  • 初始时,协程对象处于等待状态,表示它可以被等待执行。当协程对象被事件循环调度执行时,进入运行状态。最终,当协程对象执行完成时,进入完成状态。
import asyncioasync def my_coroutine():# 协程逻辑await asyncio.sleep(1)return "Coroutine finished"coro = my_coroutine()  # 创建协程对象
print(coro)  # <coroutine object my_coroutine at 0x7f1e5c0b5d60>
print(coro.cr_running)  # False,表示协程对象不在运行状态
print(coro.cr_await)  # None,表示协程对象没有被等待

三、事件循环

        事件循环(Event Loop)是协程编程中的核心概念,用于调度和执行协程对象。它负责协调协程的执行顺序,处理协程的挂起和恢复,并管理异步操作的完成事件。

1、创建事件循环

  • 在 Python 中,可以通过 asyncio 模块的 get_event_loop() 方法来获取默认的事件循环对象。
  • 也可以使用 asyncio 模块的 new_event_loop() 方法来创建新的事件循环对象。
import asyncioloop = asyncio.get_event_loop()  # 获取默认的事件循环对象
# 或者
loop = asyncio.new_event_loop()  # 创建新的事件循环对象

2、注册协程对象

  • 使用事件循环的 create_task() 方法可以将协程对象注册到事件循环中,以便事件循环调度其执行。
  • 注册后的协程对象会在事件循环的调度下按照顺序执行。
import asyncioasync def my_coroutine():# 协程逻辑await asyncio.sleep(1)print("Coroutine finished")loop = asyncio.get_event_loop()
task = loop.create_task(my_coroutine())  # 注册协程对象到事件循环

3、运行事件循环

  • 通过调用事件循环的 run_until_complete() 方法,并传入需要运行的协程对象,可以启动事件循环并运行协程直到其完成。
  • 在运行过程中,事件循环会根据协程的状态和事件的发生情况,决定哪个协程继续执行、哪个协程挂起等。
import asyncioasync def my_coroutine():# 协程逻辑await asyncio.sleep(1)print("Coroutine finished")async def main():loop = asyncio.get_event_loop()task = loop.create_task(my_coroutine())  # 注册协程对象到事件循环await taskasyncio.run(main())  # 运行事件循环,直到协程完成

4、控制事件循环

  • 事件循环提供了一些方法来控制其行为,如 stop() 方法用于停止事件循环的运行,is_running() 方法用于检查事件循环是否在运行中等。
  • 可以使用 run_forever() 方法来启动事件循环,并使其一直运行,直到手动停止。
import asyncioasync def my_coroutine():# 协程逻辑await asyncio.sleep(1)print("Coroutine finished")async def main():loop = asyncio.get_event_loop()task = loop.create_task(my_coroutine())  # 注册协程对象到事件循环await taskloop.stop()  # 停止事件循环loop = asyncio.get_event_loop()
loop.run_until_complete(main())  # 运行事件循环,直到协程完成

四、异步操作和挂起点

异步操作和挂起点是协程编程中的关键概念,用于处理并发任务和实现非阻塞的异步操作。

1、异步操作

  • 异步操作是指可以在后台进行而不会阻塞程序执行的操作。这些操作通常涉及 IO 操作、网络请求、数据库查询等耗时的任务。
  • 在传统的同步编程中,这些操作会阻塞程序的执行,直到操作完成才能继续执行后续代码。而在异步编程中,这些操作可以在后台进行,程序可以继续执行其他任务。
  • 异步操作通常是通过使用异步库、框架或语言提供的异步函数来实现。

2、挂起点(Suspend Point)

  • 挂起点是协程中的一个特殊位置,在该位置协程可以暂时挂起自身的执行,让出事件循环的控制权,等待某个条件满足或异步操作完成后再继续执行。
  • 挂起点通常通过使用 await 表达式来实现,它用于等待一个异步操作的完成,并将控制权交给事件循环。
  • 在挂起点之前的代码会被执行,但在挂起点之后的代码在等待期间不会执行,直到挂起点恢复执行。
import asyncioasync def my_coroutine():print("Before await")await some_async_operation()  # 挂起点print("After await")async def some_async_operation():await asyncio.sleep(1)  # 模拟异步操作asyncio.run(my_coroutine())

3、挂起和恢复

  • 当协程遇到挂起点时,它会暂停执行,并将控制权交给事件循环,以便在等待期间执行其他协程或异步操作。
  • 一旦挂起点等待的条件满足或异步操作完成,协程会从挂起点恢复执行,并继续执行挂起点之后的代码。
  • 挂起和恢复的过程是通过事件循环的调度来实现的,事件循环会根据协程的状态和事件的发生情况,决定哪个协程继续执行、哪个协程挂起等。
import asyncioasync def my_coroutine():print("Before await")await some_async_operation()  # 挂起点print("After await")async def some_async_operation():await asyncio.sleep(1)  # 模拟异步操作asyncio.run(my_coroutine())

五、并发执行协程

        并发执行协程是协程编程的一个重要特性,它允许多个协程同时执行,以提高程序的性能和响应能力。

1、并发与并行

  • 在讨论并发执行协程之前,需要明确并发和并行的概念。
  • 并发是指多个任务在同一时间段内交替进行,通过时间片轮转或调度算法来实现任务切换,给人一种同时执行的感觉。
  • 并行是指多个任务同时执行,需要具备多个执行单元(例如多个 CPU 核心)才能实现真正的并行执行。

2、并发执行协程的实现

  • 在协程编程中,通过事件循环(Event Loop)来实现并发执行协程。
  • 事件循环负责调度和执行协程对象,根据协程的状态和事件的发生情况,决定哪个协程继续执行、哪个协程挂起等。
  • 事件循环利用异步操作和挂起点的机制,使得协程能够在等待异步操作完成时暂停执行,并在异步操作完成后恢复执行。

3、并发执行的优势

  • 并发执行协程可以将多个任务交替执行,避免了阻塞等待的情况,提高了程序的性能和响应能力。
  • 通过合理的任务调度,可以在等待某个协程的异步操作时,切换到执行其他协程,从而充分利用 CPU 资源。

4、并发执行的实现方式

  • 使用 asyncio.gather() 函数:asyncio.gather() 函数可以接收多个协程对象作为参数,并将它们并发执行。它返回一个协程对象,可以通过 await 等待所有协程执行完成。
    import asyncioasync def coroutine1():# 协程1逻辑async def coroutine2():# 协程2逻辑async def main():await asyncio.gather(coroutine1(), coroutine2())  # 并发执行协程1和协程2asyncio.run(main())
  • 使用 asyncio.wait() 函数:asyncio.wait() 函数可以接收一个协程对象的集合,并返回一个元组,包含已完成和未完成的协程集合。可以通过 await 等待所有协程执行完成。
    import asyncioasync def coroutine1():# 协程1逻辑async def coroutine2():# 协程2逻辑async def main():coroutines = [coroutine1(), coroutine2()]done, pending = await asyncio.wait(coroutines)  # 并发执行协程集合asyncio.run(main())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/330826.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】数据结构中的隐藏玩法——栈与队列

前言&#xff1a; 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我…

【力扣刷题笔记第三期】Python 数据结构与算法

先从简单的题型开始刷起&#xff0c;一起加油啊&#xff01;&#xff01; 点个关注和收藏呗&#xff0c;一起刷题鸭&#xff01;&#xff01; 第一批题目 1.设备编号 给定一个设备编号区间[start, end]&#xff0c;包含4或18的编号都不能使用&#xff0c;如&#xff1a;418、…

安全访问python字典:避免空键错误的艺术

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、直接访问字典键的问题 三、使用get方法安全访问字典键 四、get方法的实际应…

个人IV代码签名证书1000

代码签名证书是一种用来验证代码来源、完整性和是否被篡改的数字证书。这款数字证书可以对软件代码进行数字签名&#xff0c;使得代码的发布者和接收者能够确认代码的真实性和完整性。通常代码签名证书只支持企事业单位申请&#xff0c;Certum个人IV代码签名证书是专为个人软件…

刷代码随想录有感(76):回溯算法——全排列

题干&#xff1a; 代码&#xff1a; class Solution { public:vector<int> tmp;vector<vector<int>> res;void backtracking(vector<int> nums, vector<int> used){if(tmp.size() nums.size()){res.push_back(tmp);return;}for(int i 0; i &l…

罗德里格斯公式(旋转矩阵)推导

文章目录 1. 推导2. 性质3. 参考 1. 推导 r r r为旋转轴&#xff0c; θ \theta θ为旋转角度。 先将旋转轴单位化 u r ∣ ∣ r ∣ ∣ u\frac{r}{||r||} u∣∣r∣∣r​ 旋转可以被分为垂直和旋转两个方向&#xff0c; 我们求沿轴方向的分量其实就是在求 p p p向量在 u u u方…

Mujava 工具的简单使用

首先下载openjava.jar和mujava.jar&#xff0c;以及自己手写一个mujava.config指向存放mujava的目录&#xff0c;并将这些文件放在mujava目录下。此时&#xff0c;基本的mujava环境就搭建好了。 分别创建src&#xff08;存放源码文件&#xff09;、classes&#xff08;存放源码…

从零搭建python环境:深入解析虚拟环境与Python版本管理

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;为何需要虚拟环境&#xff1f; 二、虚拟环境的创建与命名 1. 虚拟环境…

CTFHUB技能树——SSRF(二)

目录 上传文件 ​FastCGI协议 Redis协议 上传文件 题目描述&#xff1a;这次需要上传一个文件到flag.php了.祝你好运 index.php与上题一样&#xff0c;使用POST请求的方法向flag.php传递参数 //flag.php页面源码 <?phperror_reporting(0);if($_SERVER["REMOTE_ADDR&…

2024“电工杯”数学建模A题《园区微电网风光储协调优化配置》思路和代码分享

A 题&#xff1a;园区微电网风光储协调优化配置 这个题目整体就是一个优化问题&#xff0c;可以采用MatlabYalmipGurobi求解器进行求解&#xff0c;持续更新中&#xff0c;敬请关注&#xff01;&#xff01; 园区微电网由风光发电和主电网联合为负荷供电&#xff0c;为了尽量提…

【Docker】Linux 系统(CentOS 7)安装 Docker

文章目录 对 VMware 软件的建议官方说明文档Docker安装卸载旧版本docker设置仓库开始安装 docker 引擎最新版 Docker 安装指定版本 Docker 安装&#xff08;特殊需求使用&#xff09; 启动 Docker查看 Docker 版本查看 Docker 镜像设置 Docker 开机自启动 验证开机启动是否生效…

牛皮!亚信安全《2024国家级攻防演练100+必修高危漏洞合集》.pdf

上次分享了2023攻防演练高危漏洞&#xff0c;获得了很多粉丝的好评。 今天再分享一份由亚信安全服务团队结合自身的“外部攻击面管理”服务能力和专业的红队能力&#xff0c;最新发布的《2024攻防演练必修高危漏洞合集》&#xff0c;一共108页&#xff0c;非常详细&#xff0c…

windows、mac、linux中node版本的切换(nvm管理工具),解决项目兼容问题 node版本管理、国内npm源镜像切换

文章目录 在工作中&#xff0c;我们可能同时在进行2个或者多个不同的项目开发&#xff0c;每个项目的需求不同&#xff0c;进而不同项目必须依赖不同版本的NodeJS运行环境&#xff0c;这种情况下&#xff0c;对于维护多个版本的node将会是一件非常麻烦的事情&#xff0c;nvm就是…

014_C标准库函数之<stdio.h>

【背景】 今天这个主要说的是<stdio.h>头文件&#xff0c;大家众所周知&#xff0c;这个是我们学习C语言时第一个接触到的头文件了&#xff0c;那么为什么我不一开始就介绍这个头文件呢&#xff1f;我觉得有两个原因&#xff0c;如下&#xff1a; 1.一开始大家的编程思…

spring boot整合j2cache 关闭二级缓存

我们整合了 j2cache 的项目启动 日志会输出 一级缓存 二级缓存 一级是 EhCacheProvider 二级是 SpringRedisProvider 如果 我们不想用二级缓存 在 j2cache.properties 中 加上 j2cache.12-cache-open配置 值为 true/false true是启用二级缓存 false 是不起用 默认 true 所以 …

其它高阶数据结构⑦_Skiplist跳表_概念+实现+对比

目录 1. Skiplist跳表的概念 2. Skiplist跳表的效率 3. Skiplist跳表的实现 3.1 力扣1206. 设计跳表 3.2 Skiplist的初始化和查找 3.3 Skiplist的增加和删除 3.4 Skiplist的源码和OJ测试 4. 跳表和平衡搜索树/哈希表的对比 本篇完。 1. Skiplist跳表的概念 skiplist是…

AWTK实现汽车仪表Cluster/DashBoard嵌入式GUI开发(七):快启

前言: 汽车仪表是人们了解汽车状况的窗口,而仪表中的大部分信息都是以指示灯形式显示给驾驶者。仪表指示灯图案都较为抽象,对驾驶不熟悉的人在理解仪表指示灯含义方面存在不同程度的困难,尤其对于驾驶新手,如果对指示灯的含义不求甚解,有可能影响驾驶的安全性。即使是对…

人工智能应用-实验8-用生成对抗网络生成数字图像

文章目录 &#x1f9e1;&#x1f9e1;实验内容&#x1f9e1;&#x1f9e1;&#x1f9e1;&#x1f9e1;代码&#x1f9e1;&#x1f9e1;&#x1f9e1;&#x1f9e1;分析结果&#x1f9e1;&#x1f9e1;&#x1f9e1;&#x1f9e1;实验总结&#x1f9e1;&#x1f9e1; &#x1f9…

YOLOv10论文解读:实时端到端的目标检测模型

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

C#【进阶】特殊语法

特殊语法、值和引用类型 特殊语法 文章目录 特殊语法1、var隐式类型2、设置对象初始值3、设置集合初始值4、匿名类型5、可空类型6、空合并操作符7、内插字符串8、单句逻辑简略写法 值和引用类型1、判断值和引用类型2、语句块3、变量的生命周期4、结构体中的值和引用5、类中的值…