Python 中的并发 —— 事件驱动编程
摘要:Python中的事件驱动编程采用异步模型,通过事件循环监听和处理事件。Asyncio模块提供了实现单线程并发的框架,核心组件包括:事件循环(管理事件执行)、Future(表示未完成计算)、协程(可暂停/恢复的执行单元)以及传输和协议类(处理网络通信)。该模块支持通过async/await语法编写异步代码,并提供了任务并行处理能力。典型应用场景包括高效I/O操作和网络通信,能够显著提升程序性能。
目录
Python 中的并发 —— 事件驱动编程
事件驱动编程以事件为核心,程序的执行流程最终由事件决定。此前我们接触的要么是顺序执行模型,要么是并行执行模型,而融入事件驱动编程思想的模型被称为异步模型。事件驱动编程依赖一个事件循环,该循环会持续监听新到来的事件,整个编程的运行逻辑都围绕事件展开。一旦进入事件循环,事件将决定代码的执行内容与执行顺序。以下流程图可帮助理解其工作原理:开始初始化等待新事件到来解析事件并更新内部状态是否有事件处理器?否 → 关闭程序 / 系统崩溃是 → 执行处理器逻辑结束

Python 模块:Asyncio
Asyncio 模块在 Python 3.4 版本中被引入,它提供了基于协程编写单线程并发代码的底层架构。该模块核心围绕以下几个关键概念展开:
事件循环(Event Loop)
事件循环是处理计算代码中所有事件的核心功能,在整个程序执行期间持续运行,实时跟踪事件的到来与执行过程。Asyncio 模块规定每个进程仅能拥有一个事件循环。
以下是 Asyncio 模块提供的用于管理事件循环的常用方法:
loop = get_event_loop():为当前运行上下文获取对应的事件循环。loop.call_later(time_delay, callback, argument):安排回调函数在指定的time_delay秒后执行。loop.call_soon(callback, argument):安排回调函数尽快执行,回调函数会在call_soon()方法返回后,控制权交还给事件循环时触发。loop.time():根据事件循环的内部时钟,返回当前时间。asyncio.set_event_loop():将当前上下文的事件循环设置为指定的循环对象。asyncio.new_event_loop():创建并返回一个新的事件循环对象。loop.run_forever():让事件循环持续运行,直到调用stop()方法才终止。
示例:调用异步方法
以下示例通过run()方法以异步方式调用函数,实现打印 “Hello World” 的功能:
import asyncio
async def main():
print("Hello World")
# 运行异步方法
asyncio.run(main())
输出结果:
plaintext
Hello World
未来对象(Futures)
Asyncio 的 Future 类与concurrent.futures.Future类兼容,二者均代表尚未完成的计算任务。但asyncio.futures.Future与concurrent.futures.Future存在以下几点差异:
result()和exception()方法不接受超时参数,若未来对象尚未完成,调用这两个方法会直接抛出异常。- 通过
add_done_callback()注册的回调函数,始终通过事件循环的call_soon()方法触发。 asyncio.futures.Future类不兼容concurrent.futures包中的wait()和as_completed()函数。
示例:使用 Asyncio Future
以下示例帮助理解asyncio.futures.Future类的使用方式:main.py
import asyncio
async def MyOperation(future):
await asyncio.sleep(2)
future.set_result('Completed')
async def main():
# 获取当前运行的事件循环,并创建一个未来对象
loop = asyncio.get_running_loop()
future = loop.create_future()
# 创建任务并完成未来对象的计算
asyncio.create_task(MyOperation(future))
# 等待未来对象执行完成
print("Waiting for future to complete...")
result = await future
# 未来对象执行完成后,打印结果
print(f"Future result: {result}")
# 运行主方法
if __name__ == "__main__":
asyncio.run(main())
输出结果:运行代码并验证输出:
plaintext
Waiting for future to complete...
Future result: Completed
协程(Coroutines)
Asyncio 中的协程概念,与threading模块中的标准Thread对象概念相似,是子例程概念的泛化。协程在执行过程中可以被挂起,等待外部处理完成;当外部处理结束后,协程会从之前挂起的位置恢复执行。
Asyncio 中主要有两种实现协程的方式,以下为基础实现示例:
示例 1:通过async def定义协程函数
这是 Asyncio 模块中实现协程的基础方法,对应的 Python 脚本如下:main.py
import asyncio
async def MyOperation():
print("First Coroutine")
# 运行异步方法
asyncio.run(MyOperation())
输出结果:运行代码并验证输出:
plaintext
First Coroutine
示例 2:任务(Tasks)
Tasks 是 Asyncio 模块的子类,负责在事件循环中并行执行协程。以下 Python 脚本演示了如何并行处理多个任务:main.py
import asyncio
import time
async def Task_ex(n):
time.sleep(1)
print("Processing {}".format(n))
async def Generator_task():
for i in range(10):
asyncio.ensure_future(Task_ex(i))
print("Tasks Completed")
await asyncio.sleep(2)
# 运行异步方法
asyncio.run(Generator_task())
输出结果:运行上述代码并验证输出:
plaintext
Tasks Completed
Processing 0
Processing 1
Processing 2
Processing 3
Processing 4
Processing 5
Processing 6
Processing 7
Processing 8
Processing 9
传输(Transports)
Asyncio 模块提供了传输类,用于实现各类通信方式。这类类并非线程安全,且在通信通道建立后,始终会与一个协议实例配对使用。
传输类均继承自BaseTransport基类,主要包含以下几种类型:
ReadTransport:只读传输的接口。WriteTransport:只写传输的接口。DatagramTransport:用于发送数据报的接口。BaseSubprocessTransport:与BaseTransport类功能相似,适用于子进程通信。
BaseTransport基类包含五个核心方法,所有上述传输类型均继承并实现了这些方法:
close():关闭传输通道。is_closing():若传输通道正在关闭或已关闭,返回True。get_extra_info(name, default = None):获取传输通道的额外信息(如地址、端口等)。get_protocol():返回当前与传输通道配对的协议实例。
协议(Protocols)
Asyncio 模块提供了协议基类,可通过继承这些基类实现自定义的网络协议。协议类始终与传输类配合使用:
- 协议:负责解析接收到的数据,并发起对外数据的写入请求;
- 传输:负责实际的 I/O 操作和数据缓冲。
Asyncio 主要提供了三种协议基类:
Protocol:基类,用于实现流协议,适配 TCP 和 SSL 传输。DatagramProtocol:基类,用于实现数据报协议,适配 UDP 传输。SubprocessProtocol:基类,用于实现与子进程通信的协议,通信基于一组单向管道完成。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)