深入理解Python中的async和await用法

文章目录

  • 任务处理方式
  • 异步操作的优缺点
  • async和awiat
  • async
  • await
  • 使用 async/await 的注意事项
  • 示例
  • 前言:此篇文章是在文心一言的辅助下完成的。

    任务处理方式

  • 同步操作:同步操作是指所有的操作都完成后,才返回给用户结果。当一个任务发出请求并等待响应时,如果未收到响应,该任务就会被阻塞,并一直等待直到收到响应为止。例如,在一个同步过程中,如果有一个函数需要较长时间才能返回结果,那么主线程将一直等待该函数的返回,期间无法执行其他任务。
  • 异步操作:异步操作是指两个或多个任务相互独立地执行,其中一个任务不需要等待另一个任务的完成就能开始执行自己的操作。即使某个任务需要等待其他任务的结果,它也不会被阻塞,而是可以继续执行后续的操作。例如,在异步编程中,即使有一个函数需要较长时间才能返回结果,主线程也可以继续执行后面的语句,当该函数返回结果后,通常会通过回调函数的方式通知主线程,并在回调函数中处理该任务的结果。
  • 异步操作的优缺点

    异步操作指的是每个终端在消息传输中使用独立的时钟源。具体来说,异步操作中的每一个任务都有一个或多个回调函数(callback)。当一个任务结束后,不是立即执行下一个任务,而是执行相应的回调函数。同时,下一个任务会在前一个任务还在等待回调函数执行时就开始执行。因此,程序的执行顺序与任务的排列顺序是不一致的。

    异步操作的优点主要有以下几点:

    1. 无需额外的线程负担:异步操作无需创建新的线程来处理任务,而是使用回调的方式进行处理,这降低了系统的开销。
    2. 减少死锁的可能性:在设计良好的情况下,异步操作的处理函数可以不必使用共享变量,或者至少可以减少共享变量的数量,从而降低了发生死锁的可能性。
    3. 提高程序响应性:异步操作允许在等待某些任务(如I/O操作)完成时,继续执行其他任务,从而提高了程序的响应性和效率。
    4. 适用于I/O密集型应用程序:由于异步操作在处理I/O操作时具有优势,因此它特别适用于这类应用程序。

    然而,异步操作也存在一些缺点:

    1. 编程复杂度较高:编写异步操作的程序复杂度相对较高,主要因为需要使用回调方式进行处理,这与普通人的思维方式有所出入。
    2. 难以调试:由于异步操作的非顺序性和回调机制,调试过程可能会变得相对困难。
    3. 错误处理复杂:在异步编程中,错误处理可能变得更为复杂,因为错误可能发生在回调函数中,需要特别注意错误传播的路径。

    async和awiat

    在 Python 中,asyncawait 是用于处理异步编程的关键字,它们一起工作,使得编写异步代码更加直观和简单。异步编程是一种编程模型,它允许程序在等待某些操作(如 I/O 操作)完成时,继续执行其他任务,从而提高程序的响应性和效率。

    async

    async 关键字用于定义异步函数。异步函数使用 async def 语法,而不是普通的 def 语法。异步函数内部通常包含 await 表达式,用于等待异步操作完成。

    示例:

    async def my_async_function():
        print("Start of my_async_function")
        await some_other_async_function()
        print("End of my_async_function")
    

    在这个例子中,my_async_function 是一个异步函数。它首先打印一条消息,然后等待 some_other_async_function 完成(假设这也是一个异步函数),最后打印另一条消息。

    await

    await 关键字用于在异步函数中等待异步操作完成。它只能用在异步函数内部。当 Python 遇到 await 表达式时,它会暂停当前函数的执行,直到等待的异步操作完成。

    示例:

    import asyncio
    
    async def my_async_function():
        print("Start of my_async_function")
        await asyncio.sleep(1)  # 等待 1 秒
        print("End of my_async_function")
    
    # 获取事件循环
    loop = asyncio.get_event_loop()
    # 运行异步函数
    loop.run_until_complete(my_async_function())
    

    在这个例子中,my_async_function 使用了 await 来等待 asyncio.sleep(1) 完成。这会导致函数暂停执行 1 秒,然后继续执行。

    使用 async/await 的注意事项

    1. 只能在异步函数中使用 await:你不能在普通函数中使用 await
    2. 异步函数通常使用 await 调用其他异步函数:这是异步编程模型的核心部分,它允许程序在等待异步操作完成时继续执行其他任务。
    3. 异步函数通常使用 asyncio 库进行事件循环和调度asyncio 是 Python 的标准异步 I/O 库,它提供了用于异步编程的各种工具和功能。
    4. 注意异常处理:异步函数中可能会抛出异常,你需要使用 try/except 块来捕获和处理这些异常。

    示例

    首先,我们需要一个异步函数来模拟获取网页内容的过程。

    import asyncio
    import aiohttp
    
    async def fetch_page(session, url):
        async with session.get(url) as response:
            return await response.text()
    

    然后,我们可以创建一个异步函数来并发地获取多个网页的内容。这个函数使用了asyncio.gather来并发执行多个异步任务。

    async def fetch_multiple_pages(urls):
        async with aiohttp.ClientSession() as session:
            tasks = [fetch_page(session, url) for url in urls]
            return await asyncio.gather(*tasks)
    

    最后,我们可以编写一个主函数来调用这个异步函数,并打印出获取到的网页内容。

    async def main():
        urls = [
            'https://example.com',
            'https://google.com',
            'https://python.org',
        ]
        contents = await fetch_multiple_pages(urls)
        for url, content in zip(urls, contents):
            print(f"Contents of {url}:\n{content[:100]}...\n")
    
    # Python 3.7+
    asyncio.run(main())
    

    在这个例子中,fetch_multiple_pages函数会并发地获取多个网页的内容,而不是一个接一个地顺序获取。这大大提高了程序的效率,特别是在网络请求较多的情况下。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 深入理解Python中的async和await用法

    发表评论