深入理解 Python 中的异步操作:async 和 await

目录

一、异步编程基础

1. 同步与异步

2. 异步编程的优势

3. 异步编程的难点

二、async 和 await 简介

1. async 关键字

2. await 关键字

三、async 和 await 的用法

1. 异步函数的定义

2. 调用异步函数

3. 异步函数中的 await

四、异步编程中的常见模式

1. 并发执行多个异步任务

2. 异常处理

3. 异步上下文管理器

五、实战案例:异步网络请求

1. 安装 aiohttp

2. 异步网络请求示例

六、总结


在 Python 编程中,异步操作是处理 I/O 密集型任务(如网络请求、文件读写等)的一种高效方式。通过异步操作,程序可以在等待 I/O 操作完成的同时执行其他任务,从而显著提高整体性能。Python 3.5 引入了 async 和 await 关键字,使得编写异步代码变得更加直观和简洁。本文将带你深入理解这两个关键字,并通过代码和案例展示其用法。

一、异步编程基础

在深入 async 和 await 之前,我们先来了解一下异步编程的基本概念。

1. 同步与异步

  • 同步:任务按顺序执行,一个任务完成后才执行下一个任务。
  • 异步:任务可以并发执行,不必等待一个任务完成后再执行下一个任务。
  • 2. 异步编程的优势

  • 提高性能:在等待 I/O 操作(如网络请求)时,可以执行其他任务。
  • 资源利用:更有效地利用系统资源,避免阻塞。
  • 3. 异步编程的难点

  • 代码复杂度:异步代码通常比同步代码更难理解和调试。
  • 错误处理:需要特别注意异步操作中的错误处理。
  • 二、async 和 await 简介

    1. async 关键字

    async 关键字用于定义一个异步函数。异步函数在调用时不会立即执行,而是返回一个 awaitable 对象(通常是 Asyncio 协程)。

    2. await 关键字

    await 关键字用于等待一个 awaitable 对象完成。它只能在 async 函数内部使用。当 await 一个异步函数时,当前协程会暂停执行,直到被等待的异步函数完成,然后恢复执行。

    三、async 和 await 的用法

    1. 异步函数的定义

    使用 async 关键字定义一个异步函数:

    async def my_async_function():
        # 异步代码
        pass

    2. 调用异步函数

    异步函数在调用时不会立即执行,而是返回一个 awaitable 对象。要等待异步函数完成,可以使用 await 关键字(通常在另一个异步函数内部):

    import asyncio
    
    async def main():
        result = await my_async_function()
        print(result)
     
    # 注意:不能直接调用 main(),需要使用事件循环来运行它
    
     
    asyncio.run(main())

    3. 异步函数中的 await

    在异步函数内部,可以使用 await 等待其他异步函数或异步操作完成:

    import asyncio
     
    async def fetch_data_from_api():
        # 模拟网络请求
        await asyncio.sleep(1)  # 异步等待 1 秒
        return "Data from API"
     
    async def main():
        data = await fetch_data_from_api()
        print(data)
     
    asyncio.run(main())

    四、异步编程中的常见模式

    1. 并发执行多个异步任务

    使用 asyncio.gather() 可以并发执行多个异步任务:

    import asyncio
     
    async def task1():
        await asyncio.sleep(1)
        return "Task 1 complete"
     
    async def task2():
        await asyncio.sleep(2)
        return "Task 2 complete"
     
    async def main():
        results = await asyncio.gather(task1(), task2())
        print(results)
     
    asyncio.run(main())

    在这个例子中,task1 和 task2 会并发执行,而不是按顺序执行。

    2. 异常处理

    在异步函数中,可以使用 try…except 语句来处理异常:

    import asyncio
     
    async def faulty_task():
        await asyncio.sleep(1)
        raise ValueError("An error occurred")
     
    async def main():
        try:
            await faulty_task()
        except ValueError as e:
            print(f"Caught an exception: {e}")
     
    asyncio.run(main())

    3. 异步上下文管理器

    Python 3.7 引入了异步上下文管理器,允许在异步代码中使用 async with 语句:

    import asyncio
     
    class AsyncContextManager:
        async def __aenter__(self):
            print("Entering context")
            return self
     
        async def __aexit__(self, exc_type, exc_val, exc_tb):
            print("Exiting context")
     
    async def main():
        async with AsyncContextManager() as ctx:
            await asyncio.sleep(1)
            print("Inside context")
     
    asyncio.run(main())

    五、实战案例:异步网络请求

    下面是一个使用 aiohttp 库进行异步网络请求的示例。aiohttp 是一个支持异步 I/O 的 HTTP 客户端/服务器库。

    1. 安装 aiohttp

    首先,需要安装 aiohttp 库:

    pip install aiohttp

    2. 异步网络请求示例

    import aiohttp
    import asyncio
     
    async def fetch(session, url):
        async with session.get(url) as response:
            return await response.text()
     
    async def main():
        async with aiohttp.ClientSession() as session:
            html = await fetch(session, 'http://example.com')
            print(html[:100])  # 打印前 100 个字符
     
    asyncio.run(main())

    在这个例子中,我们使用 aiohttp.ClientSession() 创建一个会话对象,并使用 await session.get(url) 发送异步 GET 请求。然后,我们使用 await response.text() 获取响应的文本内容。

    六、总结

    async 和 await 是 Python 中处理异步操作的关键字,它们使得编写异步代码变得更加直观和简洁。通过异步编程,我们可以更有效地利用系统资源,提高程序的性能。本文介绍了 async 和 await 的基本概念、用法以及异步编程中的常见模式,并通过实战案例展示了如何使用它们进行异步网络请求。希望这些内容能帮助你更好地理解和使用 Python 中的异步操作。

    作者:傻啦嘿哟

    物联沃分享整理
    物联沃-IOTWORD物联网 » 深入理解 Python 中的异步操作:async 和 await

    发表回复