asyncio使用介绍

当然可以!下面是对 Python 中 asyncio详细介绍,从基础原理到核心用法,再到实际场景和注意事项,帮助你全面理解这个模块。



🧠 一、什么是 asyncio

asyncio 是 Python 的标准库(自 Python 3.4 引入,3.7 起成熟),用于 编写异步IO代码

它通过 事件循环(event loop)+ 协程(coroutines) 实现非阻塞异步操作,允许在单线程中同时处理成百上千个任务。



🧩 二、核心概念

1. 协程(Coroutine)

协程是一种比线程更轻量的并发机制。

  • 用 async def 定义。
  • 用 await 调用其他协程或异步操作。
async def say_hello():
    await asyncio.sleep(1)
    print("Hello")


2. 事件循环(Event Loop)

事件循环是 asyncio 的调度引擎:

  • 注册任务
  • 监听事件
  • 调度执行协程
asyncio.run(main())  # 启动事件循环


3. await 与 异步非阻塞

await挂起当前协程,把控制权交还给事件循环,等被等待的操作完成后再继续执行。



🔧 三、常用 API 和用法

1. asyncio.run(coro)

  • 启动并运行事件循环,直到协程运行完。
async def main():
    await asyncio.sleep(1)
    print("Done")

asyncio.run(main())


2. asyncio.sleep(sec)

  • 非阻塞地等待一段时间,用于模拟 IO 等待。
await asyncio.sleep(2)


3. asyncio.gather(*tasks)

asyncio.gather(*tasks)返回结果的顺序是固定的严格按照传入协程的顺序返回结果与每个任务完成的先后顺序无关

  • 并发运行多个协程,所有任务完成后返回结果列表。
async def job(n):
    await asyncio.sleep(n)
    return f"Job {n} done"

results = await asyncio.gather(job(1), job(2), job(3))


4. asyncio.create_task(coro)

  • await 会挂起当前协程,直到目标协程完成,而 create_task() 立即启动协程的执行,不会挂起当前函数的执行。
  • 如果直接使用 await 执行协程,程序会阻塞,直到该协程完成。而 create_task() 则是非阻塞的,它允许你在等待协程的同时执行其他任务。
    • 显式创建一个协程任务,立即调度执行。
    async def do_work():
        await asyncio.sleep(2)
        print("Work done")
    
    async def main():
        task = asyncio.create_task(do_work())
        print("Task created")
        await task
    
    asyncio.run(main())
    


    🚀 四、使用场景

    ✅ 非常适合:

    • 网络请求(如 HTTP、WebSocket)
    • 数据库异步驱动(如 asyncpg, aiomysql)
    • 高并发爬虫、API 调用
    • 定时任务、消息推送系统


    ⚠️ 五、注意事项

    1. await 只能在 async def 函数中使用。

    # 错误示例
    await asyncio.sleep(1)  # SyntaxError
    

    2. 协程本身不会运行,必须由事件循环驱动:

    # 错误示例
    coro = async_func()
    coro()  # 不会执行!
    

    3. 异步 ≠ 多线程。asyncio单线程非阻塞模型,适用于 IO 密集,不适合 CPU 密集型任务。



    🏗️ 六、实战示例:并发抓取网页标题

    import asyncio
    import aiohttp  # 异步HTTP库
    
    async def fetch_title(url):
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                html = await response.text()
                print(f"{url} title length: {len(html)}")
    
    async def main():
        urls = ['https://www.python.org', 'https://www.github.com', 'https://www.google.com']
        tasks = [fetch_title(url) for url in urls]
        await asyncio.gather(*tasks)
    
    asyncio.run(main())
    


    🔄 七、和多线程/多进程的对比

    特性asyncio(协程)threading(线程)multiprocessing(进程)
    模型单线程、事件驱动多线程、抢占式调度多进程、进程间通信
    开销低(轻量协程)中(线程上下文切换)高(进程创建和IPC)
    使用场景IO密集、网络应用IO密集或部分CPU任务CPU密集任务


    ✅ 总结

    功能点asyncio 提供的能力
    并发执行任务asyncio.gather, create_task
    非阻塞等待await, asyncio.sleep
    启动/关闭事件循环asyncio.run, loop.run_forever
    异步库支持aiohttp, aiomysql, asyncpg


    文章标签:

    评论(0)