asyncio 库核心方法详解【Python】

部署运行你感兴趣的模型镜像

asyncio 库核心方法详解

asyncio 是 Python 用于编写并发代码的库,使用 async/await 语法。它特别适合 IO 密集型和高并发网络应用。下面我将详细讲解 asyncio 的核心方法。

1. 事件循环 (Event Loop)

事件循环是 asyncio 的核心,负责调度和执行异步任务。

主要方法:

  • asyncio.get_event_loop() - 获取当前事件循环
  • asyncio.set_event_loop(loop) - 设置当前事件循环
  • asyncio.new_event_loop() - 创建新的事件循环
  • loop.run_until_complete(future) - 运行直到 future 完成
  • loop.run_forever() - 一直运行,直到调用 loop.stop()
  • loop.stop() - 停止事件循环
  • loop.close() - 关闭事件循环
  • loop.is_running() - 检查事件循环是否正在运行
  • loop.is_closed() - 检查事件循环是否已关闭
import asyncio

async def example_coroutine(name, seconds):
    """示例协程函数"""
    print(f"协程 {name} 开始运行,将等待 {seconds} 秒")
    await asyncio.sleep(seconds)
    print(f"协程 {name} 完成")
    return f"{name}-结果"

def main():
    # 创建一个新的事件循环
    loop = asyncio.new_event_loop()
    
    try:
        # 设置为当前线程的事件循环
        asyncio.set_event_loop(loop)
        
        # 检查事件循环状态
        print(f"事件循环正在运行吗?: {loop.is_running()}")  # False
        print(f"事件循环已关闭吗?: {loop.is_closed()}")    # False
        
        # 创建几个协程任务
        coro1 = example_coroutine("任务A", 2)
        coro2 = example_coroutine("任务B", 1)
        
        # 将协程包装为Future/Task
        task1 = loop.create_task(coro1)
        task2 = asyncio.ensure_future(coro2)
        
        # 运行直到所有任务完成
        print("开始运行事件循环...")
        loop.run_until_complete(asyncio.gather(task1, task2))
        
        # 获取任务结果
        print(f"任务1结果: {task1.result()}")
        print(f"任务2结果: {task2.result()}")
        
        # 演示 run_forever 和 stop
        async def stop_after(seconds):
            await asyncio.sleep(seconds)
            loop.stop()
            
        print("\n演示 run_forever 和 stop...")
        loop.create_task(example_coroutine("后台任务", 1))
        loop.create_task(stop_after(3)) # 只要loop不关闭就不会结束运行,而asyncio.gather(task1, task2)只要所有的task执行结束就会停止
        loop.run_forever()
        
    finally:
        # 关闭事件循环
        if not loop.is_closed():
            loop.close()
        print(f"事件循环已关闭吗?: {loop.is_closed()}")  # True

if __name__ == "__main__":
    main()

>>>
事件循环正在运行吗?: False
事件循环已关闭吗?: False
开始运行事件循环...
协程 任务A 开始运行,将等待 2 秒
协程 任务B 开始运行,将等待 1 秒
协程 任务B 完成
协程 任务A 完成
任务1结果: 任务A-结果
任务2结果: 任务B-结果

演示 run_forever 和 stop...
协程 后台任务 开始运行,将等待 1 秒
协程 后台任务 完成
事件循环已关闭吗?: True

2. 协程 (Coroutines)

协程是 asyncio 的基本执行单元,使用 async def 定义。

主要方法:

  • asyncio.coroutine(func) - 将生成器函数标记为协程(旧式)
  • asyncio.iscoroutine(obj) - 检查对象是否是协程
  • asyncio.iscoroutinefunction(func) - 检查函数是否是协程函数

3. Tasks 和 Futures

Future

Future 代表异步操作的最终结果。

  • asyncio.Future() - 创建一个 Future 对象
  • future.done() - 检查是否完成
  • future.result() - 获取结果(如果未完成会阻塞)
  • future.exception() - 获取异常
  • future.add_done_callback(cb) - 添加完成回调

Task

Task 是 Future 的子类,用于调度协程的执行。

  • asyncio.create_task(coro) - 将协程包装为 Task 并调度执行
  • asyncio.ensure_future(obj) - 确保对象是 Future/Task
  • task.cancel() - 取消任务
  • task.cancelled() - 检查是否被取消

4. 运行和等待

  • asyncio.run(coro) - 运行协程(Python 3.7+)
  • asyncio.gather(*coros_or_futures) - 并发运行多个协程
  • asyncio.wait(fs) - 等待一组 Future 完成
  • asyncio.wait_for(fut, timeout) - 带超时的等待
  • asyncio.shield(fut) - 防止任务被取消

示例代码

from time import sleep
import asyncio
import time 
import random

async def greet(name):
    print("Hello, " + name)
    await asyncio.sleep(2)
    print("Goodbye, " + name)


async def seed_coroutine():
    print('Seeding...')
    await send_request()
    print('Done Seeding')

async def send_request():
    print('Sending request...')
    sleep_time = random.randint(5, 10)
    print(f'Sleeping for {sleep_time} seconds...')
    await asyncio.sleep(sleep_time)
    print('Request sent')

async def main():
    start_time = time.time()
    task1 = asyncio.create_task(greet("Alice")) # 创建任务,用于并发执行多个协程任务
    task2 = asyncio.create_task(greet("Bob"))
    await asyncio.gather(task1, task2) # 协调任务,用于等待多个协程任务的全部完成
    print(f"Time elapsed: {time.time() - start_time} seconds")
    task3 = asyncio.create_task(seed_coroutine())
    task4 = asyncio.create_task(seed_coroutine())
    await asyncio.gather(task3, task4)
    print(f"Time elapsed: {time.time() - start_time} seconds")

# 运行主函数
if __name__ == "__main__":
    asyncio.run(main())

>>>
Hello, Alice
Hello, Bob
Goodbye, Alice
Goodbye, Bob
Time elapsed: 2.001737117767334 seconds
Seeding...
Sending request...
Sleeping for 6 seconds...
Seeding...
Sending request...
Sleeping for 6 seconds...
Request sent
Done Seeding
Request sent
Done Seeding
Time elapsed: 8.004700183868408 seconds

5. 同步原语

asyncio 提供了类似于 threading 的同步原语:

  • asyncio.Lock() - 互斥锁
  • asyncio.Event() - 事件
  • asyncio.Condition() - 条件变量
  • asyncio.Semaphore() - 信号量
  • asyncio.BoundedSemaphore() - 有界信号量

6. 网络和子进程

  • asyncio.open_connection() - 打开 TCP 连接
  • asyncio.start_server() - 启动 TCP 服务器
  • asyncio.create_subprocess_exec() - 创建子进程
  • asyncio.create_subprocess_shell() - 通过 shell 创建子进程

7. 实用工具

  • asyncio.sleep(delay) - 异步休眠
  • asyncio.get_running_loop() - 获取当前运行的事件循环
  • asyncio.current_task() - 获取当前任务
  • asyncio.all_tasks() - 获取所有任务

最佳实践

实践示例

简易IO流
  • 异步字节流
import asyncio

class AsyncBytesIO:
    """简易异步字节流实现"""
    def __init__(self):
        self._buffer = bytearray()
        self._eof = False
        self._waiters = []

    async def write(self, data):
        """异步写入数据"""
        if self._eof:
            raise IOError("Stream closed")
        self._buffer.extend(data)
        # 唤醒所有等待读取的协程
        for fut in self._waiters:
            if not fut.done():
                fut.set_result(None)
        self._waiters.clear()

    async def read(self, n=-1):
        """异步读取数据"""
        while not self._buffer and not self._eof:
            # 等待数据到达
            fut = asyncio.get_running_loop().create_future()
            self._waiters.append(fut)
            try:
                await fut
            except:
                self._waiters.remove(fut)
                raise
        
        if n < 0 or n > len(self._buffer):
            data = bytes(self._buffer)
            self._buffer.clear()
        else:
            data = bytes(self._buffer[:n])
            del self._buffer[:n]
        return data

    async def close(self):
        """关闭流"""
        self._eof = True
        for fut in self._waiters:
            if not fut.done():
                fut.set_result(None)

注意

  • 尽量使用 asyncio.run() 而不是手动管理事件循环

  • 使用 create_task() 来调度协程

  • 避免在协程中使用阻塞 IO 操作

  • 合理使用 asyncio.gather() 来并发运行多个协程

  • 注意异常处理,使用 try/except 捕获协程中的异常

asyncio 提供了强大的异步编程能力,理解这些核心方法是掌握 Python 异步编程的关键。

run_forever() 方法与run_until_complete(gather())对比
行为特征run_forever()run_until_complete(gather())
停止条件必须显式调用 loop.stop()所有task完成自动停止
任务监控不自动监控任务完成状态显式监控指定任务的完成状态
适用场景长期运行的服务有限任务的批量执行
任务结束后事件循环继续空转事件循环自动结束
是否需要清理需要手动停止和关闭循环自动管理循环生命周期

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值