Python协程技术:从Greenlet到async/await的异步编程探索

news2024/9/24 23:02:23

协程:

​ 协程,在Python中,协程是一种轻量级的并发编程方式,它允许在单个线程内实现多个独立的执行流。协程可以在不同的执行点之间进行切换,而无需依赖于操作系统的线程切换。这使得协程成为处理高并发和异步任务的有力工具。

def func1():
	print(1)
    ...
	print(2)
	
def func2():
	print(3)
    ...
	print(4)

func1()
func2()

​ 上述代码是普通的函数定义和执行,按流程分别执行两个函数中的代码,并先后会输出:1、2、3、4。但如果介入协程技术那么就可以实现函数见代码切换执行,最终输入:1、3、2、4

例如:下面的代码可以实现协程

import asyncio

async def func1():
    print(1)
    await asyncio.sleep(1)  # 模拟耗时操作
    print(2)

async def func2():
    print(3)
    await asyncio.sleep(1)  # 模拟耗时操作
    print(4)

async def main():
    await asyncio.gather(func1(), func2())

asyncio.run(main())

在这里插入图片描述

协程的实现

在Python中,有多种方式可以实现协程。以下是其中几种常用的方式:

  • 使用第三方模块greenlet:greenlet是一个第三方库,它提供了协程的支持。通过使用greenlet,可以手动控制协程的切换,并实现协程之间的交替执行。
  • 使用生成器(yield):Python中的生成器也可以用于实现协程,通过yield关键字可以暂停函数的执行,并在需要时恢复执行。生成器可以作为协程函数,通过yield来实现协程的切换。
  • 使用asyncio库:Python标准库中的asyncio模块提供了对协程的支持。asyncio提供了事件循环(event loop)和协程(coroutine)的概念,可以通过async/await关键字来定义和管理协程,实现异步编程。
  • 使用async/await关键字:在Python 3.5及更高版本中,引入了async/await关键字,使得编写和管理协程更加方便。通过使用async/await关键字结合asyncio库,可以轻松地定义和管理协程,并实现异步编程。
1.greenlet
from greenlet import greenlet

def func1():
    print(1)        # 第1步:输出 1
    gr2.switch()    # 第3步:切换到 func2 函数
    print(2)        # 第6步:输出 2
    gr2.switch()    # 第7步:切换到 func2 函数,从上一次执行的位置继续向后执行

def func2():
    print(3)        # 第4步:输出 3
    gr1.switch()    # 第5步:切换到 func1 函数,从上一次执行的位置继续向后执行
    print(4)        # 第8步:输出 4

gr1 = greenlet(func1)
gr2 = greenlet(func2)
gr1.switch() # 第1步:去执行 func1 函数

在这里插入图片描述

提示:switch中也可以传递参数用于在切换执行时相互传递值。

2. yield

​ 生成器的yield关键字可以用于实现协程代码。通过使用yield,可以将函数切分为多个可暂停和恢复的执行点,从而实现协程的切换。

yield from可以用于等待另一个协程的执行,并将控制权转移到该协程,直到它完成或产生结果。这样可以实现协程的嵌套和协作,使得协程能够在遇到IO操作时暂停执行,并自动切换到其他协程

def func1():
    yield 1
    yield from func2()
    yield 2


def func2():
    yield 3
    yield 4


f1 = func1()
for item in f1:
    print(item)

在这里插入图片描述

3.asyncio

在Python 3.4发布后,官方引入了asyncio模块,为Python提供了官方支持的协程和异步编程框架。asyncio模块基于事件循环和协程的概念,提供了一种方便的编程模型来实现异步操作。

import asyncio

@asyncio.coroutine
def func1():
    print(1)
    yield from asyncio.sleep(2)  # 遇到IO耗时操作,自动化切换到tasks中的其他任务
    print(2)


@asyncio.coroutine
def func2():
    print(3)
    yield from asyncio.sleep(2) # 遇到IO耗时操作,自动化切换到tasks中的其他任务
    print(4)


tasks = [
    asyncio.ensure_future( func1() ),
    asyncio.ensure_future( func2() )
]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

在这里插入图片描述

4 async & awit

在Python 3.5版本中,引入了asyncawait关键字,它们被用作协程的定义和异步操作的等待。相比于使用@asyncio.coroutine装饰器和yield from语法,使用asyncawait关键字能够使协程代码更加简洁和易读。

从Python 3.8版本开始,官方已经不推荐使用@asyncio.coroutine装饰器,而是建议直接使用asyncawait关键字来定义协程函数和等待异步操作的完成。这样可以提高代码的可读性和维护性,同时也更符合Python语言的发展趋势。

import asyncio

async def func1():
    print(1)
    await asyncio.sleep(2)  # 遇到IO耗时操作,自动化切换到tasks中的其他任务
    print(2)


async def func2():
    print(3)
    await asyncio.sleep(2)  # 遇到IO耗时操作,自动化切换到tasks中的其他任务
    print(4)


tasks = [
    asyncio.ensure_future(func1()),  # 将func1协程函数转换为Task对象
    asyncio.ensure_future(func2())   # 将func2协程函数转换为Task对象
]

loop = asyncio.get_event_loop()  # 创建事件循环对象
loop.run_until_complete(asyncio.wait(tasks))  # 运行协程任务直到所有任务完成

asyncio模块的核心是事件循环(event loop),它负责调度和执行协程任务。通过使用asyncawait关键字,可以定义协程函数,并在协程函数内使用await关键字来暂停协程的执行,等待异步操作的完成。

总结:

​ 在本文中,我们深入探索了Python中的协程技术,从传统的Greenlet和yield到新的async/await关键字,涵盖了多种实现协程的方法。通过这些技术,我们能够以非阻塞的方式处理并发和异步操作,提高程序的性能和响应能力。

​ 协程是一种轻量级的并发编程模型,允许我们在单个线程内实现多个独立的执行流。使用Greenlet和yield,我们可以手动切换协程的执行,实现协程间的协作。这种方式虽然灵活,但需要手动编写切换逻辑,不太直观。

​ 随着asyncio模块的引入,Python提供了更高级的异步编程功能。通过使用其中的协程和事件循环,我们可以更方便地定义和调度协程,处理IO密集型任务和并发操作。asyncio提供了丰富的工具和函数,使得异步编程变得简洁和可读性更强。

​ 最新的async/await关键字进一步简化了协程的编写和理解。通过使用async/await,我们可以直接在协程函数中等待异步操作的完成,而不再需要使用yield from语法。这使得协程代码更加易读和直观,符合Python的语法风格。

​ 总而言之,协程技术为我们提供了一种高效的并发编程方式。无论是处理IO密集型任务还是构建高性能的网络应用,协程都能发挥重要的作用。通过选择合适的工具和语法,我们可以根据具体的需求和编程风格,灵活地应用协程技术。掌握协程的概念和实现方式,将有助于提升代码的性能和可维护性,让我们在异步编程的世界中更加游刃有余。

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

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

相关文章

大语言模型新升级:亚马逊云科技2023芯片创新日

在这个充满活力的2023年芯片创新日,Amazon EC2 的副总裁 Dave Brown 与观众分享了他与 EC2 的15年漫长旅程。他的眼中闪烁着对技术的热情,他描述了自己如何与一个才华横溢的团队合作,在这大语言模型与生成式AI的元年中致力于为客户提供最佳的…

Python基础语法之学习字符串快速格式化

Python基础语法之学习字符串快速格式化 一、代码二、效果 一、代码 # 通过f"{占位}"控制字符串快速格式化,不做精度控制 name "张三" age 13 money 12.5 text f"姓名是{name},年龄是{age},钱是{money}" print(text)二、效果 每一天都是一个…

Codeforces Round 906 (Div. 2)(D推公式 E1分类讨论区间 E2 dp+线段树)

A - Doremys Paint 3 推公式得 b1b3b5b7.... b2b4b6b8... 所以如果只有一个数或者两个数且数量差小于等于1即可 #include<bits/stdc.h> using namespace std; const int N 2e510,mod1000003; #define int long long typedef long long LL; typedef pair<int, in…

idea类和方法模版

类模版 修改目标位置 class #if (${PACKAGE_NAME} && ${PACKAGE_NAME} ! "")package ${PACKAGE_NAME};#end #parse("File Header.java")/*** ${Description}* author whc ${YEAR}/${MONTH}/${DAY}* version v1.0 */public class ${NAME} { }inte…

#HarmonyOS:软件安装

软件地址 https://developer.harmonyos.com/cn/develop/deveco-studio#download 安装的建议 这个界面这样选&#xff0c;其他界面全部按照默认路径往下走&#xff01;&#xff01;&#xff01; 等待安装… 安装环境错误处理 一般就是本地node配置一场导致&#xff0c;建议…

在Pycharm中创建项目新环境,安装Pytorch

在python项目中&#xff0c;很多项目使用的各类包的版本是不一致的。所以我们可以对每个项目有专属于它的环境。所以这个文章就是教你如何创建新环境。 一、创建新环境 首先我们需要去官网下载conda。然后在Pycharm下面添加conda的可执行文件。 用conda创建新环境。 二、…

Netfilter中的NAT

目录 前瞻 SNAT和DNAT SNAT DNAT 实验 前瞻 NAT: &#xff08;network address translation&#xff09;&#xff0c;支持PREROUTING&#xff0c;INPUT&#xff0c;OUTPUT&#xff0c;POSTROUTING四个链 NAT分为SNAT和DNAT SNAT&#xff1a;支持POSTROUTING, INPUT&…

Java封装讯飞星火大模型历险记

问题描述与分析 现状描述与目标 在使用讯飞星火大模型API的过程中&#xff0c;API的返回结果在可以在其他线程中进行分次打印&#xff0c;但是在main方法中直接打印返回结果&#xff0c;显示为空。这种情况下不利于二次封装&#xff0c;希望在main方法中获取完整的API返回结果…

POE浪涌保护器+POE防雷器综合解决方案

POE&#xff08;Power over Ethernet&#xff0c;以太网供电&#xff09;是一种利用双绞线以太网布线同时传输电力和数据的技术&#xff0c;目前常用于智能安防摄像系统、无线局域网、物联网等领域。POE技术可以简化网络设备的布线和安装&#xff0c;降低成本和维护难度&#x…

文献速递:机器学习在超声波非破坏性评估中的合成和增强训练数据综述(第一部分)— (机器学习方法在超声波检测中的概述)

文献速递&#xff1a;机器学习在超声波非破坏性评估中的合成和增强训练数据综述&#xff08;第一部分&#xff09;— &#xff08;机器学习方法在超声波检测中的概述&#xff09; Title 题目 A review of synthetic and augmented training data for machine learning in ul…

python用YOLOv8对图片进行分类

用yolov8的模型进行分类 先上效果图 图片资源 模型下载地址 https://github.com/ultralytics/ultralytics 代码 import matplotlib.pyplot as plt from ultralytics import YOLO from PIL import Image import cv2model YOLO(../ultralytics/yolov8n.pt)# print(model…

代码随想录算法训练营第四十八天【动态规划part09】 | 198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 求解思路&#xff1a; 当前房屋偷与不偷取决于前一个房屋是否被偷了 动规五部曲 确定dp数组及其下标含义&#xff1a;考虑下标i&#xff08;包括i&#xff09…

Nginx(无法解析PHP网页如何解决?FPM解决你的烦恼!)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xff1a;云计算技…

新建的springboot项目中application.xml没有绿色小叶子(不可用)

经常有朋友会遇到新建了一个springboot项目&#xff0c;发现为啥我创建的application.xml配置文件不是绿色的&#xff1f;&#xff1f;&#xff1f; 下面教大家如何解决&#xff0c;这也是博主在做测试的时候遇到的&#xff1a; 将当前位置application.xml删掉&#xff0c;重新…

RF实现数据驱动DDT

场景 在自动化测试框架中&#xff0c;数据驱动的意思指定的是测试用例或者说测试套件是由外部数据集合来驱动的框架。这里说的数据集可以是任何类型的数据文件比如xls&#xff0c;xlsx&#xff0c;csv等等。它的核心的思想就是数据和测试代码分离&#xff0c;及时当测试数据发…

【同济大学主办】第七届先进算法与控制工程国际学术会议(ICAACE 2024)

第七届先进算法与控制工程国际学术会议&#xff08;ICAACE 2024&#xff09; 2024 7th International Conference on Advanced Algorithms and Control Engineering 第七届先进算法与控制工程国际学术会议&#xff08;ICAACE 2024&#xff09;定于2024年1月26-28日在中国上…

虽然在不同设备上会出现同样的原神错误代码9907,但解决办法因设备而异

你是不是很享受在原神(Genshin Impact)中的神奇旅程,但错误代码9907出现了?与PS4控制台中全面讨论PS4的错误CE-34878-0不同,本文关注的是原神错误本身。本文不仅讨论了这个错误背后的原因,还讨论了每种类型设备的具体解决方案。 在Microsoft Windows/PC上修复错误代码99…

深入学习redis-基于Jedis通过客户端操作Redis

目录 redis客户端&#xff08;JAVA&#xff09; 配置 引入依赖 建立连接 常用命令实现 get/set exists/del keys expire和ttl type 字符串&#xff08;String&#xff09; mget和mset getrange和setrange append incr和decr 列表&#xff08;list&#xff09; …

自动化测试 —— 如何优雅实现方法的依赖!

在 seldom 3.4.0 版本实现了该功能。 在复杂的测试场景中&#xff0c;常常会存在用例依赖&#xff0c;以一个接口自动化平台为例&#xff0c;依赖关系&#xff1a; 创建用例 --> 创建模块 --> 创建项目 --> 登录。 用例依赖的问题 •用例的依赖对于的执行顺序有严格…

好用的chatgpt工具用过这个比较快

chatgpthttps://www.askchat.ai?r237422 chatGPT能做什么 1. 对话和聊天&#xff1a;我可以与您进行对话和聊天&#xff0c;回答您的问题、提供信息和建议。 2. 问题回答&#xff1a;无论是关于事实、历史、科学、文化、地理还是其他领域的问题&#xff0c;我都可以尽力回答…