Python 异步编程原理篇之新旧协程实现对比
2024/1/16 14:02:33
本文主要是介绍Python 异步编程原理篇之新旧协程实现对比,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
协程的发展流程
再来回顾一下协程的发展流程:
python2.5 为生成器引用.send()、.throw()、.close()方法
python3.3 为引入yield from,可以接收返回值,可以使用yield from定义协程
Python3.4 加入了asyncio模块
Python3.5 增加async、await关键字,在语法层面的提供支持
python3.7 使用 async def + await 的方式定义协程
python3.10 移除 以 yield from 的方式定义协程
旧协程
是指以yield
、yield from
等生成器语法为基础的协程实现新协程
是指以asyncio
、async
、await
等关键字为基础的协程实现
两种协程的实现方式在协程发展史上有一段交集,并且旧协程基于生成器的协程语法让生成器和协程两个概念混淆,所以对学习者会造成一定的困扰。本篇主要说明两种协程的实现方式的差异。
旧协程回顾
旧协程以yield关键字为核心,通过yield关键提供的代码执行暂停、恢复的能力,实现函数交替的执行,cpu的转让等能力。
import time def consume(): r = '' while True: n = yield r print(f'[consumer] 开始消费 {n}...') time.sleep(1) r = f'{n} 消费完成' def produce(c): next(c) n = 0 while n < 5: n = n + 1 print(f'[producer] 生产了 {n}...') r = c.send(n) print(f'[producer] consumer return: {r}') c.close() if __name__=='__main__': c = consume() produce(c)
执行结果:
[producer] 生产了 1... [consumer] 开始消费 1... [producer] consumer return: 1 消费完成 [producer] 生产了 2... [consumer] 开始消费 2... [producer] consumer return: 2 消费完成 [producer] 生产了 3... [consumer] 开始消费 3... [producer] consumer return: 3 消费完成 [producer] 生产了 4... [consumer] 开始消费 4... [producer] consumer return: 4 消费完成 [producer] 生产了 5... [consumer] 开始消费 5... [producer] consumer return: 5 消费完成
结果分析:
当消费者consume
执行到n = yield r
时,流程暂停,将cpu交还给调用方produce
。
在asyncio初识篇中提到过,协程最重要的两个因素是事件循环
+ 任务
。用yield实现的协程中,consume
和 produce
中的 while循环共同作用下实现了一个事件循环的功能,yield
和 send
实现了任务的暂停和继续执行。
总结来说协程需要的两个能力事件循环
和任务暂停和继续
,在旧协程中的实现分别是:
- 事件循环通过手动编写while循环代码实现
- 代码暂停继续执行通过yield生成器的能力实现
新协程回顾
新协程是asyncio
、async
、await
等关键字实现的。新协程是基于事件循环机制实现的,核心能力包括事件循环,任务,回调机制等。三者提供的能力分别是
- asyncio 提供了事件循环
- async 提供了协程标识
- await 提供了流程挂起能力
import asyncio async def coro1(): print("start coro1") await asyncio.sleep(2) print("end coro1") async def coro2(): print("start coro2") await asyncio.sleep(1) print("end coro2") # 创建事件循环 loop = asyncio.get_event_loop() # 创建任务 task1 = loop.create_task(coro1()) task2 = loop.create_task(coro2()) # 运行协程 loop.run_until_complete(asyncio.gather(task1, task2)) # 关闭事件循环 loop.close()
结果
start coro1 start coro2 end coro2 end coro1
结果分析:
当coro1
执行到 await asyncio.sleep(2)
时,流程挂起,将cpu交还给事件循环,等待事件循环的下一次调度,而事件循环调度到coro2
继续执行。
协程的两个重要能力事件循环
和 任务暂停和继续
,分别的实现者:
- 事件循环通过asyncio提供的loop实现
- 程序挂起通过 await 关键字实现
新酒协程实现的对比
asyncio
和 yield
是用于实现异步编程的两种不同的机制。
yield
是一种用于生成器(Generator)函数的关键字,用于创建可暂停和恢复执行的函数。当一个函数中包含 yield
语句时,它会返回一个生成器对象,可以通过调用生成器的 next()
方法或使用 for
循环来逐步迭代生成器函数中的值。
通过使用 yield
,我们可以将一个函数分割成多个代码块,并在每个代码块之间进行切换执行。这使得我们可以在函数执行过程中临时挂起函数的执行,然后再次恢复执行。
asyncio
是 Python 提供的标准库,用于编写异步代码。它基于事件循环(Event Loop)模式,允许我们在单线程中处理多个并发任务,并通过协程(Coroutine)来管理异步操作。
asyncio
使用了 async
和 await
这两个关键字来定义协程函数。在协程函数中可以使用 await
关键字来暂停当前协程的执行,等待某个异步操作的完成,然后恢复执行。
总结来说:
旧协程:通过yield关键字的暂停和恢复执行的能力实现协程
新协程:通过事件循环机制,await关键字挂起流程能力实现协程
await 和 yield 的关系
await
关键字和 yield
关键字都可以用于控制流的暂停和恢复,都属于python的关键字,但是它们在协程的实现上有所不同。
相同点:
-
控制流暂停和恢复:无论是
await
还是yield
,它们都可以使代码在某个点暂停执行,并在稍后的时间点继续执行。 -
协程支持:
await
和yield
都与协程(Coroutine)密切相关。它们都能够用于定义和管理协程,使得异步代码的编写更加简单和易读。
区别:
-
语法差异:
await
是 Python 3.5 引入的关键字,用于异步函数中暂停执行等待异步操作完成。而yield
是早期协程的关键字,主要用于生成器(Generator)函数,用于创建迭代器和实现惰性计算,早期通过生成器的能力来实现协程。 - 语义:
-
await
表示当前协程需要等待一个异步操作的完成,并挂起执行,让其他任务有机会执行。 -
yield
是将执行的控制权交给调用方,同时保存函数的状态,以便在下次迭代时从上一次暂停的位置恢复执行。await将程序挂起,让事件循环调度新的任务。yield将程序挂起,等待调用方的下一步指令。
-
上下文:
await
必须在异步上下文中使用,例如在异步函数中或者在async with
块中。而yield
可以在普通函数中使用,即使没有使用协程的上下文。 -
返回值:
yield
返回生成器对象,通过调用next()
方法或使用for
循环逐步迭代生成器中的值。而await
返回一个可等待对象(Awaitable),它可以是Future
、Task
、Coroutine
等。
总结:
await 不是通过 yield 来实现的程序暂停和执行,两者有相似的能力,但完全没有调用关系,都是属于python关键字。
-
await
适用于异步编程场景,用于等待异步操作的完成,同时支持更灵活的协程管理。 -
yield
则主要用于生成器函数,用于实现迭代器和惰性计算。
它们在应用场景和语法上存在一些差异,但都为我们提供了控制流的暂停和恢复的能力。
以上就是新旧协程的实现方法,对比了两种协程的实现方法,比较了yield关键字既作为生成器又实现协程有点混淆的用法,比较了都可以暂停恢复的关键字yield和await。这些内容是协程原理的核心知识,理解有难度。
这篇关于Python 异步编程原理篇之新旧协程实现对比的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门
- 2024-11-14Python编程入门指南
- 2024-11-13Python基础教程
- 2024-11-12Python编程基础指南
- 2024-11-12Python基础编程教程
- 2024-11-08Python编程基础与实践示例
- 2024-11-07Python编程基础指南
- 2024-11-06Python编程基础入门指南
- 2024-11-06怎么使用python 计算两个GPS的距离功能-icode9专业技术文章分享