Python 协程(Coroutine):轻量级的并发执行单元

协程(Coroutine):轻量级的并发执行单元

协程是一种用户态线程,可以在执行过程中暂停并在适当时候恢复,是 Python 异步编程的核心。它比线程更轻量(无需内核切换),特别适合 I/O 密集型任务。


核心特性

特性说明
协作式调度主动让出执行权(非抢占式)
状态保持暂停时保留局部变量和执行位置
高效并发单线程内处理数千个并发任务
双向通信可通过 yieldawait 发送/接收数据

协程与生成器的关系

协程是生成器的进化版,两者都使用 yield,但目的不同:

# 生成器(数据生产者)
def generator():
    yield 1
    yield 2

# 协程(数据处理者)
def coroutine():
    data = yield  # 等待接收数据
    print(f"Received: {data}")

Python 协程演进史

  1. 基于生成器的协程(Python 2.5+)

    def old_coroutine():
        received = yield "ready"
        print(f"Got: {received}")
    
    c = old_coroutine()
    print(next(c))  # 输出: ready
    c.send("data")  # 输出: Got: data
    
  2. 原生协程(Python 3.5+)

    async def modern_coroutine():
        print("Start")
        await asyncio.sleep(1)  # 非阻塞等待
        print("End")
    

协程、生成器、迭代器的关系

可迭代对象
迭代器
生成器
协程
  • 迭代器:提供 __next__() 的惰性数据流
  • 生成器:用 yield 实现的迭代器
  • 协程:扩展生成器,支持双向通信和异步操作

协程使用场景

场景优势
网络请求(HTTP/DB)等待时不阻塞线程
高并发服务器单线程处理数千连接
数据流管道优雅连接处理步骤
状态机实现自然表达复杂状态

现代协程(async/await)

Python 3.5+ 原生支持:

import asyncio

async def fetch(url):
    # 模拟网络请求
    await asyncio.sleep(0.5)
    return f"Data from {url}"

async def main():
    # 并发执行3个请求
    results = await asyncio.gather(
        fetch("url1"),
        fetch("url2"),
        fetch("url3")
    )
    print(results)  # 约0.5秒后输出所有结果

# 运行事件循环
asyncio.run(main())

协程关键组件

  1. 事件循环(Event Loop)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(task)
    
  2. Future 对象

    fut = asyncio.Future()
    fut.set_result(42)  # 设置结果
    
  3. Task 对象

    task = asyncio.create_task(coroutine())
    

协程 vs 线程

特性协程线程
切换开销纳秒级(用户态切换)微秒级(内核切换)
并发数量单线程可处理数万协程通常数百
数据共享无需锁(单线程)需要同步机制
适用场景I/O密集型CPU密集型
调试难度较高(异步逻辑)中等

典型协程模式

  1. 生产者-消费者管道
async def producer(queue):
    while True:
        item = generate_item()
        await queue.put(item)

async def consumer(queue):
    while True:
        item = await queue.get()
        process(item)
  1. 超时控制
async def fetch_with_timeout():
    try:
        async with asyncio.timeout(1.0):  # Python 3.11+
            await long_running_task()
    except TimeoutError:
        print("Timeout!")

协程最佳实践

  1. 避免阻塞调用

    # 错误 ❌
    await asyncio.sleep(1)
    time.sleep(1)  # 阻塞整个线程!
    
    # 正确 ✅
    await asyncio.sleep(1)
    
  2. 使用异步库

    # 同步库(阻塞)
    import requests
    
    # 异步替代 ✅
    import aiohttp
    
  3. 限制并发量

    sem = asyncio.Semaphore(10)  # 最大10并发
    
    async def limited_task():
        async with sem:
            await resource_intensive_task()
    

总结:Python 执行单元演进

概念特点典型实现
可迭代对象支持多次迭代list, dict
迭代器记录状态的惰性迭代iter([1,2,3])
生成器动态生成值的迭代器(x for x in ...)
协程可暂停恢复的并发执行单元async def

核心价值:协程在单线程内实现高并发,用同步写法处理异步操作,是现代化 Python 高性能应用的基石。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值