Python 中的 IO 模型总结

Python 中的 IO 模型总结

一、IO 的分类与区别

类型描述举例
阻塞 IOIO 调用会一直等待数据就绪,期间无法做其他事sock.recv()(默认)
非阻塞 IOIO 调用立即返回,数据没准备好时返回错误/空sock.setblocking(False)
IO 多路复用使用 select / poll / epoll 同时监听多个 IO 通道select.select()
信号驱动 IOIO 就绪时,内核使用信号通知用户程序少见
异步 IO(AIO)用户发起 IO 后立即返回,内核完成 IO 后通知用户处理数据asyncio / aiofiles 等


二、非阻塞 IO 的本质

  • 调用立即返回,不管数据是否就绪。

  • 用户需要反复轮询(或使用 select/epoll)来检查数据是否可读。

  • 使用场景:服务端处理高并发连接(如 socket 编程)。

python

复制编辑

sock.setblocking(False)
try:
    data = sock.recv(1024)
except BlockingIOError:
    # 数据没准备好,手动处理其他任务
    pass

三、异步 IO 的本质

异步 IO = 非阻塞 IO + 事件循环(Event Loop)

特点:

  • 使用 async/await 写法像同步代码一样简单

  • 事件循环自动调度任务,不需要手动轮询

  • 程序不会被 await 阻塞,而是挂起当前任务,继续执行其他任务

  • IO 一旦就绪,自动恢复挂起的协程

python

复制编辑

async def handle_client(reader, writer):
    data = await reader.read(1024)  # IO 等待期间可以去处理其他任务
    writer.write(b"ok")
    await writer.drain()

四、async 和 await 的作用

关键字作用
async声明一个协程函数,返回的是一个“协程对象”
await暂停当前协程执行,等待一个异步操作完成,再继续执行

  • 其本质是:await 会调用目标对象的 __await__() 方法

  • 事件循环会将协程对象调度成任务,并在等待完成后自动唤醒


五、异步 IO 的底层流程(以 asyncio 为例)

  1. 程序调用 async def 定义的函数,得到协程对象

  2. 协程对象被 asyncio.run() 或事件循环调度为任务

  3. 遇到 await 时,挂起当前协程,执行其他任务

  4. IO 完成后,唤醒挂起的协程,继续执行

  5. 所有协程完成后,程序退出


六、阻塞 VS 非阻塞 VS 异步小结

模型是否阻塞主线程是否自动调度写法复杂度并发性能使用场景
阻塞 IO 是 否    简单     差简单客户端、脚本
非阻塞 IO 否 否(需手动轮询)    复杂     好高并发服务、低层 socket 编程
异步 IO 否 是(事件循环)    简单   最优Web 服务、爬虫、文件 IO 等


七、相关术语回顾

  • 事件循环(Event Loop):不断检查所有挂起任务/IO 状态,并在合适时机恢复执行。

  • 协程(Coroutine):可挂起、恢复的函数,比线程更轻量。

  • __await__:被 await 调用时执行的底层方法,返回一个迭代器对象,告诉事件循环“我等什么”。

  • 非阻塞:不会让程序停在某一步等待,而是能继续往下运行。

  • 异步:逻辑上的分离,IO 和计算不阻塞彼此。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值