asyncio基本用法介绍


asyncio 是 Python 标准库中用于 异步编程并发任务 管理的核心库。它的基础是事件循环,用来调度协程(coroutines),让它们能够非阻塞地并发执行。这种编程模型在处理大量 I/O 密集型任务时非常高效,如网络操作、文件读写等。

一、asyncio 的核心概念

  1. 协程(Coroutines)

    • 协程是 asyncio 中的基本单元,使用 async def 定义。
    • 使用 await 调用另一个协程,表示暂停当前协程,等待被调用的协程完成后再继续。
    • 它们是异步执行的,不会阻塞整个程序。
    async def my_coroutine():
        print("开始")
        await asyncio.sleep(1)  # 模拟异步操作
        print("结束")
    
  2. 事件循环(Event Loop)

    • asyncio 的核心,管理协程的执行顺序。
    • 事件循环负责调度多个协程,轮流执行它们。它允许一个协程在等待时,另一个协程可以使用 CPU 进行其他工作。
    • 使用 asyncio.run() 启动事件循环。
    async def main():
        await my_coroutine()
    
    asyncio.run(main())  # 启动事件循环
    
  3. 任务(Tasks)

    • 任务是协程的一种封装,它表示一个并发执行的协程。使用 asyncio.create_task() 来创建任务。
    • 任务会立即运行,允许多个任务同时进行。
    async def my_task():
        print("任务执行")
        await asyncio.sleep(1)
    
    async def main():
        task = asyncio.create_task(my_task())  # 创建并发任务
        await task
    
    asyncio.run(main())
    
  4. Future

    • Future 是一个低层次的对象,表示一个将来会有结果的异步操作。协程与任务本质上也是基于 Future 的封装。
    • 一般不需要直接操作 Future,而是通过协程或任务来间接使用它们。

二、asyncio 的常见用法

  1. awaitasync def

    • await 用于在协程中等待其他异步操作完成,async def 用于定义协程。
    async def fetch_data():
        await asyncio.sleep(2)  # 模拟网络请求
        return "数据"
    
    async def main():
        result = await fetch_data()
        print(result)
    
    asyncio.run(main())
    
  2. 并发任务:asyncio.create_task()asyncio.gather()

    • asyncio.create_task() 创建一个并发任务,立即执行。
    • asyncio.gather() 可以同时执行多个协程,返回它们的结果。
    async def task1():
        await asyncio.sleep(2)
        return "任务1完成"
    
    async def task2():
        await asyncio.sleep(1)
        return "任务2完成"
    
    async def main():
        result1 = asyncio.create_task(task1())
        result2 = asyncio.create_task(task2())
        await result1
        await result2
        print("所有任务完成")
    
    asyncio.run(main())
    
  3. 同步等待多个任务:asyncio.gather()

    • 同时启动多个协程,并等待它们全部完成。
    async def task1():
        await asyncio.sleep(2)
        return "任务1完成"
    
    async def task2():
        await asyncio.sleep(1)
        return "任务2完成"
    
    async def main():
        results = await asyncio.gather(task1(), task2())
        print(results)
    
    asyncio.run(main())
    
  4. 超时处理:asyncio.wait_for()

    • 可以为一个协程设置超时时间,防止协程执行时间过长。
    async def task():
        await asyncio.sleep(3)
        return "完成"
    
    async def main():
        try:
            result = await asyncio.wait_for(task(), timeout=2)  # 设置2秒超时
            print(result)
        except asyncio.TimeoutError:
            print("任务超时")
    
    asyncio.run(main())
    
  5. 同步等待:asyncio.sleep()

    • 用于模拟异步任务中的延迟,或者简单地让协程在特定时间内暂停。
    async def main():
        print("开始")
        await asyncio.sleep(2)  # 暂停2秒
        print("结束")
    
    asyncio.run(main())
    
  6. 同步进程:asyncio.run_in_executor()

    • 将阻塞的操作(如文件读写、网络请求等)交给线程池或进程池,避免阻塞事件循环。
    import asyncio
    import concurrent.futures
    
    def blocking_task():
        print("阻塞任务执行中...")
        return "完成"
    
    async def main():
        loop = asyncio.get_running_loop()
        with concurrent.futures.ThreadPoolExecutor() as pool:
            result = await loop.run_in_executor(pool, blocking_task)
            print(result)
    
    asyncio.run(main())
    

三、asyncio 中的同步原语

  1. asyncio.Event()

    • 用于在线程或协程之间传递简单的信号,允许一个或多个协程等待某个事件发生。
    async def waiter(event):
        print("等待事件...")
        await event.wait()
        print("事件触发!")
    
    async def main():
        event = asyncio.Event()
        waiter_task = asyncio.create_task(waiter(event))
        await asyncio.sleep(2)
        print("触发事件")
        event.set()
        await waiter_task
    
    asyncio.run(main())
    
  2. asyncio.Lock()

    • 一个异步锁,确保多个协程在同一时间只能有一个协程访问某个资源。
    async def task(lock):
        print("等待锁...")
        async with lock:  # 获取锁
            print("获得锁")
            await asyncio.sleep(2)
        print("释放锁")
    
    async def main():
        lock = asyncio.Lock()
        await asyncio.gather(task(lock), task(lock))
    
    asyncio.run(main())
    
  3. asyncio.Queue()

    • 一个线程安全的异步队列,允许多个生产者和消费者协程安全地传递数据。
    async def producer(queue):
        for i in range(5):
            await asyncio.sleep(1)
            await queue.put(i)
            print(f"生产者放入: {i}")
    
    async def consumer(queue):
        while True:
            item = await queue.get()
            print(f"消费者取出: {item}")
            if item == 4:
                break
    
    async def main():
        queue = asyncio.Queue()
        await asyncio.gather(producer(queue), consumer(queue))
    
    asyncio.run(main())
    

四、asyncio 中的网络操作

asyncio 还可以用于构建高效的异步网络服务,如 TCP/UDP 服务器和客户端。通过 asyncio.start_server()asyncio.open_connection() 等函数,开发者可以构建异步的网络应用。

async def handle_client(reader, writer):
    data = await reader.read(100)
    message = data.decode()
    print(f"收到消息: {message}")

    writer.write(data)
    await writer.drain()
    writer.close()

async def main():
    server = await asyncio.start_server(handle_client, '127.0.0.1', 8888)
    async with server:
        await server.serve_forever()

asyncio.run(main())

五、asyncio 的调试工具

  1. asyncio.all_tasks():查看所有当前活动的任务。
  2. asyncio.current_task():查看当前正在运行的任务。
  3. asyncio.Task.get_stack():查看任务的当前堆栈信息,用于调试。

总结

  • 协程 是异步执行的基本单元,使用 async def 定义。
  • 事件循环asyncio 的核心,用来调度协程和任务。
  • 使用 任务 (asyncio.create_task()) 和 gather 并发执行多个协程。
  • asyncio 还提供了丰富的 同步原语(如 EventLock)和高效的 I/O 操作支持

asyncio 在处理并发 I/O 密集型任务时非常强大,使用它可以避免传统多线程编程中的锁和上下文切换开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值