跳转到内容

Python 协程

来自代码酷

Python协程[编辑 | 编辑源代码]

协程(Coroutine)是Python中实现并发编程的一种轻量级方式,它允许函数在执行过程中暂停并在稍后恢复,而不阻塞整个线程。协程通过协作式多任务处理,使得多个任务可以在单个线程上高效切换,适用于I/O密集型操作。

简介[编辑 | 编辑源代码]

协程是一种特殊的生成器(Generator),它不仅可以生成值,还可以接收值。Python通过`async`和`await`关键字提供原生支持,使得协程的编写更加直观。协程的主要优势在于:

  • 轻量级:比线程更节省资源。
  • 非阻塞:适合处理高延迟的I/O操作(如网络请求、文件读写)。
  • 高效:通过事件循环(Event Loop)管理任务调度。

基本语法[编辑 | 编辑源代码]

Python使用`async def`定义协程函数,并通过`await`调用其他协程或异步操作。

import asyncio

async def hello():
    print("Hello")
    await asyncio.sleep(1)  # 模拟I/O操作
    print("World")

# 运行协程
asyncio.run(hello())

输出:

Hello
(等待1秒)
World

协程与生成器的区别[编辑 | 编辑源代码]

协程是生成器的扩展,但两者关键区别在于:

  • 生成器(Generator)通过`yield`产生值,但不能接收外部输入(除非使用`.send()`方法)。
  • 协程(Coroutine)通过`await`挂起执行,并可以接收外部输入。

事件循环(Event Loop)[编辑 | 编辑源代码]

事件循环是协程调度的核心,负责管理多个协程的执行顺序。Python的`asyncio`模块提供了默认的事件循环实现。

graph LR A[协程1] -->|await| B[I/O操作] B -->|完成| C[协程2] C -->|await| D[I/O操作] D -->|完成| A

实际案例:并发HTTP请求[编辑 | 编辑源代码]

以下示例展示如何使用协程并发发送多个HTTP请求:

import aiohttp
import asyncio

async def fetch_url(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def main():
    urls = ["https://example.com", "https://example.org"]
    tasks = [fetch_url(url) for url in urls]
    results = await asyncio.gather(*tasks)
    for result in results:
        print(len(result))  # 打印网页内容长度

asyncio.run(main())

输出:

1270  # example.com的网页长度
1234  # example.org的网页长度

协程与多线程对比[编辑 | 编辑源代码]

协程 vs 多线程
特性 协程 多线程
资源占用 低(单线程) 高(每个线程占用独立内存)
切换开销 极小(由事件循环管理) 较大(依赖操作系统调度)
适用场景 I/O密集型任务 CPU密集型任务

高级用法[编辑 | 编辑源代码]

协程嵌套[编辑 | 编辑源代码]

协程可以嵌套调用其他协程:

async def task1():
    await asyncio.sleep(1)
    return "Task 1 done"

async def task2():
    await asyncio.sleep(2)
    return "Task 2 done"

async def main():
    result1 = await task1()
    result2 = await task2()
    print(result1, result2)

asyncio.run(main())

超时控制[编辑 | 编辑源代码]

使用`asyncio.wait_for`设置超时:

async def long_running_task():
    await asyncio.sleep(10)
    return "Done"

async def main():
    try:
        result = await asyncio.wait_for(long_running_task(), timeout=5)
    except asyncio.TimeoutError:
        print("Task timed out")

asyncio.run(main())

数学基础[编辑 | 编辑源代码]

协程的调度效率可以通过吞吐量(Throughput)衡量: Throughput=Number of completed tasksTotal time

总结[编辑 | 编辑源代码]

  • 协程是Python并发编程的核心工具之一,适合I/O密集型任务。
  • 通过`async/await`语法实现,依赖事件循环调度。
  • 比多线程更轻量级,但需要显式声明异步操作。

模板:编程概念导航