Python:从头创建 Asyncio (1)

简介: Python:从头创建 Asyncio (1)

引言

现在,asyncio 已成为 Python 社区中的热门话题,并且名副其实——它提供了一种非常出色的处理 I/O 密集型程序的方法!在我探索 asyncio 的过程中,我起初并不太明白它的工作原理。但随着深入学习,我意识到 asyncio 实际上是在 Python 生成器的基础上增加了一层非常便利的封装。

本文中,我将展示如何仅用 Python 生成器来构建一个 asyncio 的简化模型。接着,我会演示如何利用 await 魔法方法,将示例代码改写为使用 async 和 await 关键字。最终,我会将我的简化版本替换为官方的 asyncio 库。通过这个过程,我相信你将对 asyncio 的神奇之处有一个更深入的理解。

生成器

如果您已经熟悉生成器,请跳过这一部分,但如果您不熟悉,那么 asyncio 就是基于它构建的,因此了解它们的工作原理非常重要。

首先,生成器之所以存在,是因为它们可以让你的代码更加内存高效。想象一下,如果您有以下循环:

for i in range(100_000_000):
    print(i)

如果 range 函数不是以生成器的形式存在,而是返回一个列表让你去遍历,那么类似上面例子的代码在内存使用上将非常浪费,因为你需要创建一个包含高达 1 亿个元素的列表。但是,由于 range 在 Python 3 或更高版本中是一个生成器,你只需在需要时逐个生成数字,而不必将整个序列一次性加载到内存中。

创建生成器有多种方法,但本文将重点介绍生成器函数。生成器函数的声明与其他函数无异,但它使用 yield 语句来逐个返回数据。这个 yield 语句将普通函数转变为一个可以按需暂停和恢复执行状态的生成器,这通过调用 next(iterator) 来实现。

例如,下面是一个生成器函数的示例:

def generator():
   yield 'hello'
   yield 'world'

iterator = generator()

当您调用生成器时,它不会像 Python 通常那样运行函数内部的代码,而是会看到yield 关键字,因此返回一个生成器对象。一旦我们有了生成器对象,我们就可以调用 next(iterator),它将运行函数的代码,直到第一个/下一个yield语句:

print(next(iterator))  # Output: hello
print(next(iterator))  # Output: world

如果我们尝试再次调用 next(iterator),生成器将引发 StopIteration 异常,因为生成器函数中不再有yield 语句。
Python 生成器的另一个很酷的功能是yield from,它允许生成器调用子生成器或可迭代对象,使您能够创建生成器链!

def generator():
   yield 'hello'

def another_generator():
   yield from generator()

iterable = another_generator()
print(next(iterable))  # Output: hello

生成器的功能远不止我提到的这些,例如生成器推导式,它与列表推导式类似,但使用的是圆括号而非方括号,还有通过 iterator.send(value) 方法向生成器传递数据的功能。不过,对于本文而言,最关键的是理解生成器能够让函数在执行过程中暂停和恢复,同时保持其内部状态。

事件循环

事件循环是 asyncio 的心脏,负责驱动和管理所有当前任务的执行,我们将首先用生成器来模拟它。虽然 asyncio 的事件循环是用 C 语言实现的,但我们可以将其想象成一个容器,里面存放着所有活跃的任务。目前,我们把这些任务看作是生成器对象。事件循环管理器会依次遍历容器中的任务,并通过调用 next(task) 函数来执行它们。当任务执行到 I/O 操作,比如等待(sleep)时,它会使用 yield 关键字来挂起当前的执行流程,并将控制权交还给事件循环,后者随后会转向执行队列中的下一个任务。

举个例子,我们有两个任务,它们首先打印出自己的任务编号,然后执行 yield 操作,这会导致它们的执行被挂起。因为事件循环管理器负责调用 next() 函数,所以在任务执行 yield 后,管理器会重新获得控制权,并继续执行循环中的下一个任务。

def task1():
   while True:
       print('Task 1')
       yield

def task2():
   while True:
       print('Task 2')
       yield

event_loop = [task1(), task2()]

while True:
   for task in event_loop:
       next(task)

随后,该代码的输出将如下所示,并且将永远持续下去,因为由于 while True 循环,两个生成器函数都永远不会完成。

Task 1
Task 2
Task 1
Task 2
…

Python Books

Python 电子书 自取链接:https://pan.quark.cn/s/b5b00664b0c0

相关文章
|
2月前
|
搜索推荐 程序员 调度
精通Python异步编程:利用Asyncio与Aiohttp构建高效网络应用
【10月更文挑战第5天】随着互联网技术的快速发展,用户对于网络应用的响应速度和服务质量提出了越来越高的要求。为了构建能够处理高并发请求、提供快速响应时间的应用程序,开发者们需要掌握高效的编程技术和框架。在Python语言中,`asyncio` 和 `aiohttp` 是两个非常强大的库,它们可以帮助我们编写出既简洁又高效的异步网络应用。
162 1
|
1月前
|
Python
Python中的异步编程:使用asyncio和aiohttp实现高效网络请求
【10月更文挑战第34天】在Python的世界里,异步编程是提高效率的利器。本文将带你了解如何使用asyncio和aiohttp库来编写高效的网络请求代码。我们将通过一个简单的示例来展示如何利用这些工具来并发地处理多个网络请求,从而提高程序的整体性能。准备好让你的Python代码飞起来吧!
75 2
|
1月前
|
调度 开发者 Python
Python中的异步编程:理解asyncio库
在Python的世界里,异步编程是一种高效处理I/O密集型任务的方法。本文将深入探讨Python的asyncio库,它是实现异步编程的核心。我们将从asyncio的基本概念出发,逐步解析事件循环、协程、任务和期货的概念,并通过实例展示如何使用asyncio来编写异步代码。不同于传统的同步编程,异步编程能够让程序在等待I/O操作完成时释放资源去处理其他任务,从而提高程序的整体效率和响应速度。
|
28天前
|
API 调度 开发者
探索Python中的异步编程:从asyncio到Trio
本文将带你深入Python异步编程的心脏地带,从asyncio的基本概念到Trio的高级特性,我们将一起揭开Python异步编程的神秘面纱,并探讨它们如何改变我们的编程方式。
|
27天前
|
API 开发者 Python
探索Python中的异步编程:Asyncio与Tornado的对决
在这个快节奏的世界里,Python开发者面临着一个挑战:如何让代码跑得更快?本文将带你走进Python异步编程的两大阵营——Asyncio和Tornado,探讨它们如何帮助我们提升性能,以及在实际应用中如何选择。我们将通过一场虚拟的“对决”,比较这两个框架的性能和易用性,让你在异步编程的战场上做出明智的选择。
|
1月前
|
数据库 Python
异步编程不再难!Python asyncio库实战,让你的代码流畅如丝!
在编程中,随着应用复杂度的提升,对并发和异步处理的需求日益增长。Python的asyncio库通过async和await关键字,简化了异步编程,使其变得流畅高效。本文将通过实战示例,介绍异步编程的基本概念、如何使用asyncio编写异步代码以及处理多个异步任务的方法,帮助你掌握异步编程技巧,提高代码性能。
74 4
|
1月前
|
API 数据处理 Python
探秘Python并发新世界:asyncio库,让你的代码并发更优雅!
在Python编程中,随着网络应用和数据处理需求的增长,并发编程变得愈发重要。asyncio库作为Python 3.4及以上版本的标准库,以其简洁的API和强大的异步编程能力,成为提升性能和优化资源利用的关键工具。本文介绍了asyncio的基本概念、异步函数的定义与使用、并发控制和资源管理等核心功能,通过具体示例展示了如何高效地编写并发代码。
42 2
|
28天前
|
测试技术 Python
Python中的异步编程与`asyncio`库
Python中的异步编程与`asyncio`库
|
1月前
|
调度 开发者 Python
异步编程在Python中的应用:Asyncio和Coroutines
异步编程在Python中的应用:Asyncio和Coroutines
29 1
|
2月前
|
关系型数据库 MySQL 数据处理
探索Python中的异步编程:从asyncio到异步数据库操作
在这个快节奏的技术世界里,效率和性能是关键。本文将带你深入Python的异步编程世界,从基础的asyncio库开始,逐步探索到异步数据库操作的高级应用。我们将一起揭开异步编程的神秘面纱,探索它如何帮助我们提升应用程序的性能和响应速度。