Python协程从入门到精通:9个案例解析yield、gevent与asyncio实战

引言

  • 痛点分析:传统多线程在高并发场景下的性能瓶颈。

  • 协程优势:轻量级、高并发、低资源消耗。

  • 本文目标:通过9个代码案例,系统讲解协程的核心技术和应用场景。

目录

引言

1. 协程基础:理解yield生成器

1.1 yield的暂停与恢复机制

1.2 生产者-消费者模型实战

1.3 双向通信:send()方法详解

2. 手动协程控制:greenlet进阶

2.1 greenlet的显式切换原理

2.2 多任务协作案例

3. 自动化协程:gevent的高效魔法

3.1 monkey.patch_all()的作用

3.2 异步I/O与阻塞切换实战

4. 官方异步框架:asyncio深度解析

4.1 async/await语法核心

4.2 事件循环与任务调度

5. 性能对比:协程 vs 同步 vs 多线程

6. 最佳实践与避坑指南

7. 扩展学习与资源推荐

结语


1. 协程基础:理解yield生成器

1.1 yield的暂停与恢复机制

通过yield关键字,函数可暂停执行并保留状态,后续通过next()send()恢复。

# 01 yield测试.py
def fun():
    print("消费者开始")
    a = yield 1  # 暂停,返回1
    print(f"接收到生产者数据: {a}")

g = fun()
print(g.send(None))  # 输出:消费者开始 → 1
g.send("饺子")       # 输出:接收到生产者数据: 饺子

1.2 生产者-消费者模型实战

通过生成器实现数据流的高效传递,避免内存浪费:

# 05 yield生产者消费者.py
def producer():
    for item in [1, 2, 3, 4, 5]:
        yield item  # 逐个生成数据

def consumer(gen):
    for item in gen:
        print(f"消费: {item}")  # 逐个消费

consumer(producer())

1.3 双向通信:send()方法详解

生成器可通过send(value)接收外部数据,实现双向交互:

# 03 yield并发测试.py
def consumer():
    while True:
        num = yield  # 接收生产者数据
        print(f"消费: {num}")

def producer():
    c = consumer()
    c.send(None)  # 启动生成器
    for i in range(3):
        c.send(i)  # 发送数据

producer()

2. 手动协程控制:greenlet进阶

2.1 greenlet的显式切换原理

greenlet通过switch()方法实现协程切换,需手动管理任务调度:

# 04 协程案例.py
from greenlet import greenlet
def task1():
    print("任务1执行")
    g2.switch()  # 切换到任务2

def task2():
    print("任务2执行")
    g1.switch()  # 切换回任务1

g1 = greenlet(task1)
g2 = greenlet(task2)
g1.switch()

2.2 多任务协作案例

模拟“学习”与“游戏”的协作式多任务:

# 06 greenlet生产者消费者.py
def producer():
    for i in range(3):
        print(f"生产: {i}")
        consumer.switch()  # 切换到消费者

def consumer():
    while True:
        print("消费中...")
        producer.switch()  # 切换回生产者

producer_g = greenlet(producer)
consumer_g = greenlet(consumer)
producer_g.switch()

3. 自动化协程:gevent的高效魔法

3.1 monkey.patch_all()的作用

通过猴子补丁替换标准库的阻塞函数(如time.sleep),实现自动协程切换:

# 07 gevent协程.py
from gevent import monkey
monkey.patch_all()  # 关键!替换阻塞函数
import gevent

def task():
    print("开始任务")
    gevent.sleep(1)  # 自动切换协程
    print("任务完成")

gevent.joinall([gevent.spawn(task) for _ in range(3)])

3.2 异步I/O与阻塞切换实战

对比协程与同步代码的效率差异(10倍性能提升):

# 08 协程效率测试.py
def sync_task():
    time.sleep(1)  # 同步阻塞

def async_task():
    gevent.sleep(1)  # 异步非阻塞

# 同步耗时10秒,协程仅1秒

4. 官方异步框架:asyncio深度解析

4.1 async/await语法核心

asyncio通过async定义协程,await触发异步等待:

# 09 asyncio测试.py
async def fetch_data():
    await asyncio.sleep(2)  # 异步等待
    return "数据"

async def main():
    result = await fetch_data()
    print(result)

asyncio.run(main())

4.2 事件循环与任务调度

事件循环(Event Loop)是asyncio的核心,负责协程的调度和执行:

loop = asyncio.get_event_loop()
tasks = [task1(), task2()]
loop.run_until_complete(asyncio.gather(*tasks))

5. 性能对比:协程 vs 同步 vs 多线程

  • 测试场景:并发执行10次1秒阻塞操作。

  • 结果

    方式 耗时 资源占用
    同步 10秒
    多线程 1秒
    协程 1秒 极低

6. 最佳实践与避坑指南

  • 调试技巧:使用logging模块记录协程状态。

  • 常见错误

    • 未调用monkey.patch_all()导致gevent失效。

    • asyncio中混用同步代码引发阻塞。

7. 扩展学习与资源推荐

  • 官方文档

    • Python asyncio

    • gevent指南

  • 书籍推荐:《Python并发编程实战》

结语

协程技术是Python高并发编程的核心,从yieldasyncio,逐层深入可大幅提升程序性能。如果本文对你有帮助,欢迎点赞收藏!

你可能感兴趣的:(Python,python,开发语言,协程,并发,yield生成器,gerrnlet,gevent)