Python中的异步:async 和 await以及操作中的事件循环、回调和异常

2024-12-29 03:50

本文主要是介绍Python中的异步:async 和 await以及操作中的事件循环、回调和异常,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Python中的异步:async和await以及操作中的事件循环、回调和异常》在现代编程中,异步操作在处理I/O密集型任务时,可以显著提高程序的性能和响应速度,Python提供了asyn...

引言

在现代编程中,异步操作是一个非常重要的概念,尤其是在处理 I/O 密集型任务时。使用异步操作可以显著提高程序的性能和响应速度。Python 提供了 asyncawait 关键字,使得编写异步代码变得更加直观和简洁。在这篇文章中,我们将深入探讨 Python 的异步操作,并通过实际代码示例来说明其使用方法。

什么是异步操作?

异步操作是一种非阻塞的编程方式,它允许程序在等待某个操作(如 I/O 操作)完成的同时继续执行其他任务。与同步操作不同,异步操作不会阻塞主线程,而是通过回调、事件循环等机制来实现并发处理。

Python android中的异步编程基础

asyncawait 关键字

  • async:定义一个异步函数。一个函数只需在 def 前面加上 async 关键字,就变成了异步函数。
  • await:等待一个异步操作的完成。只能在异步函数中使用。

asyncio 模块

asyncio 是 Python 的标准库模块,提供了对异步 I/O、事件循环、任务调度等功能的支持。

import asyncio

理论与代码示例

定义异步函数

首先,我们来定义一个简单的异步函数:

import asyncio

async def say_hello():
    print("Hello")
    await asyncio.sleep(1)  # 模拟异步操作
    print("World")

# 异步函数不会立即执行,需要在事件循环中运行

执行异步函数

要运行异步函数,需要在事件循环中调用它们。asyncio.run 是一种简洁的方式来运行异步函数。

async def main():
    await say_hello()

# 使用 asyncio.run() 启动事件循环并执行异步函数
if __name__ == "__main__":
    asyncio.run(main())

异步 I/O 操作示例

让我们编写一个更实际的示例,展示如何使用异步操作进行 I/O 密集型任务,如网络请求。

import asyncio
import aiohttp  # 需要安装 aiohttp 库: pip install aiohttp

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        "https://www.example.com",
        "https://www.python.org",
        "https://www.asyncio.org"
    ]
    
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_url(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        
        for url, content in zip(urls, results):
            print(f"URL: {url}, Content Length: {len(content)}")

if __name__ == "__main__":
    asyncio.run(main())

在这个示例中:

  1. fetch_url:这是一个异步函数,用于从指定的 URL 获取内容。
  2. main:在 main 函数中,我们定义了一组 URL,并为每个 URL 创建一个异步任务。
  3. asyncio.gather:该函数并发地运行所有任务,并等待它们全部完成。
  4. aiohttp.ClientSession:这是一个异步 HTTP 客户端会话,用于发送和接收 HTTP 请求。

高级用法:超时和取消任务

异步编程的一个重要优势是能够设置超时和取消任务。我们可以使用 asyncio.wait_for 实现这一点。

import asyncio

async def long_running_task():
    await asyncio.sleep(10)
    return "Task completed"

async def main():
    try:
        result = await asyncio.wait_for(long_running_task(), timeout=5)
        print(result)
    except asyncio.TimeoutError:
        print("The task took too long and was cancelled.")

if __name__ == "__main__":
    asyncio.run(main())

在这个示例中,如果 long_running_task 在 5 秒内没有完成,则会抛出 asyncio.TimeoutError 异常。

异步编程的优势与局限性

优势

  • 高效利用资源:异步编程可以在等待 I/O 操作完成时继续执行其他任务,从而更高效地利用 CPU 资源。
  • 提高响应速度:对于 I/O 密集型任务,异步操作可以显著提高程序的响应速度。

局限性

  • 复杂性增加:异步编程相对于同步编程来说更加复杂,需要处理事件循环、回调和异常等。
  • 调试困难:异步代码的调试和错误追踪相对较难。

事件循环、回调和异常

事件循环

理论解释

事件循环是异步编程的核心,它不断检查和处理挂起的任务和 I/O 事件。Python 的 asyncio 模块提供了对事件循环的支持。事件循环管理着所有异步任务的执行,并在任务之间切换,从而实现并发。

具体代码

import asyncio

async def say_hello():
China编程    print("Hello")
    await asyncio.sleep(1)
    print("World")

async def main():
    # 获取事件循环
    loop = asyncio.get_event_loop()
    
    # 创建任务
    task = loop.create_task(say_hello())
    
    # 运行任务
    await task

# 启动事件循环并执行主函数
if __name__ == "__main__":
    asyncio.run(main())

在这个示例中,asyncio.get_event_loop() 获取了当前的事件循环,loop.create_task() 创建了一个任务并添加到事件循环中,await task 等待任务完成。

回调

理论解释

回调函数是指在特定事件发生时自动调用的函数。在异步编程中,回调函数通常用于处理异步任务的结果或异常。asyncio 提供了多种方式来设置回调函数,包括 FutureTask 对象的 add_done_callback 方法。

具体代码

import asyncio

async def slow_operation():
    await asyncio.sleep(2)
    return "Operation Completed"

def callback(future):
    print(future.result())

async def main():
    loop = asyncio.get_event_loop()
    task = loop.create_task(slow_operation())
    task.add_done_callback(callback)
    await task

if __name__ == "__main__":
    asyncio.run(main())

在这个示例中,我们定义了一个名为 callback 的回调函数,用于处理 slow_operation 异步任务的结果。task.add_done_callback(callback) 将回调函数与任务关联,一旦任务完成,回调函数将被自动调用并打印结果。

异常处理

理论解释

在异步编程中,处理异常是至关重要的。任务在运行过程中可能会抛出异常,我们需要捕获和处理这些异常,以确保程序的稳定性。asyncio 提供了多种方式来处理异步任务中的异常。

具体代码

import asyncio

async def error_prone_operation():
    await asyncio.sleep(1)
    raise ValueError("An error occurred")

async def main():
    try:
        await error_prone_operation()
    except ValueError as e:
        print(f"Caught an exception: {e}")

if __name__ == "__main__":
    asyncio.run(main())

在这个示例中,error_prone_operation 异步函数在执行过程中可能会抛出 ValueError 异常。在 main 函数中,我们使用 try...except 块来捕获和处理这个异常,确保程序不会因为未捕获的异常而崩溃。

异步任务中的异常处理

除了直接在异步函数中捕获异常外,我们还可以在任务完成后检查异常。asyncio.Task 对象的 exception 方法可以用于检查任务是否抛出了异常。

import asyncio

async def error_prone_operation():
    await asyncio.sleep(1)
    raise ValueError("An error occurred")

async def main():
    loop = asyncio.get_event_loop()
    task = loop.create_task(error_prone_operation())
    
    try:
        await task
    except ValueError as e:
        print(f"Caught an exception: {e}")
    
    # 或者在任务完成后检查异常
    if task.exception():
        print(f"Task raised an exception: {task.exception()}")

if __name__ == "__main__":
    asyncio.run(main())

在这个示例中,我们首先在 try...except 块中捕获异常,然后在任务完成后通过 task.exception() 方法检查任务是否抛出了异常。

超时处理

在某些情况下,异步操作可能需要设置超时,以避免长时间等待。asyncio.wait_for 函数可以用于设置异步操作的超时时间。

import asyncio

async def long_running_task():
    await asyncio.sleep(10)
    return "Task completed"

async def main():
    try:
        result = await asyncio.wait_for(long_running_task(), timeout=5)
        print(result)
    except asyncio.TimeoutError:
        print("The task took too long and was cancelled.")

if __name__ == "__main__":
    asyncio.run(main())

在这个示例中,如果 long_running_task 在 5 秒内没有完成,则会抛出 asyncio.TimeoutError 异常,我们可以捕获并处理这个异常。

结论

异步编程是 Python 中处理并发和 I/O 密集型任务的一种强大工具。通过使用 asyncawaitsGTwpf 关键字,以及 asyncio 模块,我们可以编写出高效且响应迅速的异步代码。然而,异步编程也带来了更高的复杂性,因此在使用时需要仔细权衡其优势和局限性。

通过了解事件循环、回调和异常处理,我们可以更好地掌握 Python 中的异步编程。事件循环是异步编程的核心,负责管理任务的调度和执行;回调函数用于处理任务完成时的结果或异常;而异常处理则确保了程序的稳定性和健壮性。

希望通过本文的详细解释和代码示例,你能够深入理解 Python 异步编程的底层原理和实际应用。在实际项目中,合理使用这些机制,可以显著提高程序编程的性能和响应速度。

到此这篇关于Python中的异步:async 和 await以及操作中的事件循环、回调和异常的文章就http://www.chinasem.cn介绍到这了,更多相关Python中的异步操作:async 和 await内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于Python中的异步:async 和 await以及操作中的事件循环、回调和异常的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:http://www.cppcns.com/jiaoben/python/695194.html
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1152831

相关文章

Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)

《Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)》本文介绍了如何使用Python和Selenium结合ddddocr库实现图片验证码的识别和点击功能,感兴趣的朋友一起看... 目录1.获取图片2.目标识别3.背景坐标识别3.1 ddddocr3.2 打码平台4.坐标点击5.图

Python自动化Office文档处理全攻略

《Python自动化Office文档处理全攻略》在日常办公中,处理Word、Excel和PDF等Office文档是再常见不过的任务,手动操作这些文档不仅耗时耗力,还容易出错,幸运的是,Python提供... 目录一、自动化处理Word文档1. 安装python-docx库2. 读取Word文档内容3. 修改

Python重命名文件并移动到对应文件夹

《Python重命名文件并移动到对应文件夹》在日常的文件管理和处理过程中,我们可能会遇到需要将文件整理到不同文件夹中的需求,下面我们就来看看如何使用Python实现重命名文件并移动到对应文件夹吧... 目录检查并删除空文件夹1. 基本需求2. 实现代码解析3. 代码解释4. 代码执行结果5. 总结方法补充在

springboot的调度服务与异步服务使用详解

《springboot的调度服务与异步服务使用详解》本文主要介绍了Java的ScheduledExecutorService接口和SpringBoot中如何使用调度线程池,包括核心参数、创建方式、自定... 目录1.调度服务1.1.JDK之ScheduledExecutorService1.2.spring

Python自动化办公之合并多个Excel

《Python自动化办公之合并多个Excel》在日常的办公自动化工作中,尤其是处理大量数据时,合并多个Excel表格是一个常见且繁琐的任务,下面小编就来为大家介绍一下如何使用Python轻松实现合... 目录为什么选择 python 自动化目标使用 Python 合并多个 Excel 文件安装所需库示例代码

Python使用Pandas对比两列数据取最大值的五种方法

《Python使用Pandas对比两列数据取最大值的五种方法》本文主要介绍使用Pandas对比两列数据取最大值的五种方法,包括使用max方法、apply方法结合lambda函数、函数、clip方法、w... 目录引言一、使用max方法二、使用apply方法结合lambda函数三、使用np.maximum函数

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque