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.mzph.cn/news/839962.shtml

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

相关文章

【译】MySQL 组复制 - 部分网络故障对性能的影响

原文地址&#xff1a;MySQL Group Replication – Partial Network Failure Performance Impact 在这个由两部分组成的博客系列中&#xff0c;我想介绍一些使用组复制的故障转移场景。在第一部分中&#xff0c;我将讨论我在撰写这些文章时发现的一种有趣的行为和性能下降。在第…

C#学习指南:重要内容与实用技巧

学习C#编程是一段充满挑战但又非常充实的旅程。以下是我在学习过程中积累的一些经验&#xff0c;希望能对大家有所帮助。 一、掌握基础概念 类及其成员 C#中的类是编程的基础模块。理解类的结构、属性、方法和构造函数是至关重要的。每个类都有其特定的功能&#xff0c;学会如…

力扣HOT100 - 169. 多数元素

解题思路&#xff1a; 有点类似于Boyer-Moore 投票算法&#xff0c;但更加形象。 class Solution {public int majorityElement(int[] nums) {int winner nums[0];int cnt 1;for (int i 1; i < nums.length; i) {if (winner nums[i]){cnt;} else if (cn…

景源畅信数字:抖音小店新手该怎么做?

在数字化时代的浪潮中&#xff0c;抖音不仅仅是一个分享短视频的平台&#xff0c;更是一个充满潜力的电商平台。对于想要进入这个领域的朋友们来说&#xff0c;开设一家抖音小店无疑是一个既激动又迷茫的起点。那么&#xff0c;作为新手&#xff0c;该如何在这个全新的舞台上立…

【Linux】信号之信号的产生详解

&#x1f916;个人主页&#xff1a;晚风相伴-CSDN博客 &#x1f496;如果觉得内容对你有帮助的话&#xff0c;还请给博主一键三连&#xff08;点赞&#x1f49c;、收藏&#x1f9e1;、关注&#x1f49a;&#xff09;吧 &#x1f64f;如果内容有误的话&#xff0c;还望指出&…

vue核心模块源码解析

响应式原理 Object.definePropertysetterProxy var count 1 var state {} Object.defineProperty(state , count,{get(){return count},set(val){count val} }) //弊端&#xff1a;不能主动监听到对象属性的新增或者删除&#xff0c;add/deleteref和reactive 声明响应式数…

翻译《The Old New Thing》- How do I mark a shortcut file as requiring elevation?

How do I mark a shortcut file as requiring elevation? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20071219-00/?p24103 Raymond Chen 2007年12月19日 如何将快捷方式标记为需要提升权限 简要 文章介绍了如何通过设置SLDF_RUNAS_US…

许冉直播不治本,京东需要刘强东

图片&#xff5c;影视剧《纸牌屋》剧照 ©自象限原创 作者丨艾AA 编辑丨薛黎 这届618&#xff0c;消费者的热情还未显现&#xff0c;商家的怒火先爆发了。 5月21日京东618开幕次日&#xff0c;多家图书社抵制618图书大促登上了热搜。此次争议与去年双十一京东采销与电…

移动端h5适配方案:媒体查询、编写js、lib-flexible、vw、rem和vw单位换算

文章目录 各种方案第二种&#xff1a;动态设置html的font-size媒体查询mediajs 第三种&#xff1a;vw方案 rem、vw单位换算手动根据设计稿进行计算lessvs code 插件 各种方案 1&#xff09;百分比设置&#xff08;X&#xff09;【百分比很难统一&#xff0c;不推荐】 2&#xf…

安卓高级控件(下拉框、列表类视图、翻页类视图、碎片Fragment)

下拉框 此小节介绍下拉框的用法以及适配器的基本概念&#xff0c;结合对下拉框Spinner的使用说明分别阐述数组适配器ArrayAdapter、简单适配器SimpleAdapter的具体用法与展示效果。 下拉框控件Spinner Spinner是下拉框控件&#xff0c;它用于从一串列表中选择某项&#xff0…

Java与GO语言对比分析

你是不是总听到go与java种种对比&#xff0c;其中在高并发的服务器端应用场景会有人推荐你使用go而不是 java。 那我们就从两者运行原理和基本并发设计来对比分析&#xff0c;看看到底怎么回事。 运行原理对比 java java 中 jdk 已经帮我们屏蔽操作系统区别。 只要我们下载并…

Android中华为手机三态位置权限申请理解

博主前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住也分享一下给大家&#xff0c; &#x1f449;点击跳转到教程 前言&#xff1a; 使用的华为MATE 20,Android10的系统。 <!--精准定位权限&#xff0c;如&#xff1a;…

“闻起来有股答辩的味道”,答辩到底是什么味?

“闻起来有股答辩的味道”&#xff0c;答辩到底是什么味&#xff1f; 一位名叫“小鸡全家桶”的作者虚构了这样一个学校故事&#xff0c;故事说&#xff0c;由于学生的考试试卷印刷得特别模糊&#xff0c;导致里面的插图根本看不清&#xff0c;学生感到懵逼&#xff0c;监考老…

【区块链】智能合约漏洞测试

打开Ganache vscode打开智能合约漏洞工程 合约内容 pragma solidity >0.8.3;contract EtherStore {mapping(address > uint) public balances;function deposit() public payable {balances[msg.sender] msg.value;emit Balance(balances[msg.sender]);}function with…

深度学习之基于Tensorflow卷积神经网络(CNN)实现猫狗识别

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 在人工智能和深度学习的热潮中&#xff0c;图像识别是一个备受关注的领域。猫狗识别作为图像识…

权限维持--windows

隐藏文件 ①文件属性隐藏 如何排查&#xff1a; 使用dir命令无法看到有特殊属性的文件需使用/a ②真隐藏 相当于给原本的文件增加系统文件属性、存档文件属性、只读文集属性、隐藏文件属性 如何排查&#xff1a; 取消受保护的操作系统文件 ③利用ADS隐藏 使用数据流 echo &…

Docker(四) 文件和网络

1 Dockerfile 1.1 什么是Dockerfile Dockerfile是一个文本文件&#xff0c;包含一系列命令&#xff0c;这些命令用于在 Docker 镜像中自动执行操作。Dockerfile 定义了如何构建 Docker 镜像的步骤和所需的操作。 Dockerfile 中包含的命令可以设置和定制容器的环境&#xff0c;…

求第 N 个泰波那契数 | 动态规划

1.第 N 个泰波那契数 题目连接&#xff1a;1137. 第 N 个泰波那契数 泰波那契序列 Tn 定义如下&#xff1a; T0 0, T1 1, T2 1, 且在 n > 0 的条件下 Tn3 Tn Tn1 Tn2给你整数 n&#xff0c;请返回第 n 个泰波那契数 Tn 的值。 2.什么是动态规划 在解决这道问题之前…

2024年5月份最新独角数卡使用USDT详细小白教程

直观配套视频教程 2024年5月份最新独角数卡安装及USDT使用详细小白教程 1、创建服务器 Centos或者Ubuntu2、宝塔面板开心版安装寶塔 Linux 面版 8.0.5 開心版 - 2024年1月12日 - 开心专区 - 异次元 - Powered by Discuz!Centos安装命令&#xff08;默认安装是 8.0.1 直接在线升…

张大哥笔记:改变自己,才是改变一切的开始

人往往有一种惰性&#xff0c;总喜欢把希望寄托于别人&#xff01;比如会将注意力投向外部因素如环境、他人或命运从而期望为我们的生活带来突破和转机。但现实往往是残酷的&#xff0c;不会发生任何改变的&#xff01;真正的改变来自于自己&#xff0c;自我革新才是改变整个局…