0

0

使用 Asyncio 进行异步编程

WBOY

WBOY

发布时间:2024-07-23 16:19:01

|

387人浏览过

|

来源于dev.to

转载

使用 asyncio 进行异步编程

在编程世界中,“非阻塞”的概念无处不在。 javascript 开发人员经常使用术语“异步”,因为它是 javascript 的优势之一。然而,要真正理解异步编程,必须掌握并发和并行编程的概念。

并发编程

当几个独立的实体同时工作时,编程是并发的。这并不一定意味着这些任务在完全相同的时间运行。相反,它意味着任务通过共享资源(例如 cpu 时间)随着时间的推移不断取得进展。并发编程的主要优点是它的鲁棒性:如果一个进程崩溃,程序的其余部分继续运行。

并行编程

如果一个算法可以将其工作分为几个部分,那么它就是并行的。拥有的处理器越多,您从并行性中受益就越多。高效的并行编程可优化现代机器的资源以获得更好的性能。

用 cooking 说明并发与并行

并发示例:

想象一下您正在准备一顿饭,需要烤一些肉并制作酱汁。首先将肉放在烤架上。当肉烤的时候,你可以把西红柿和其他蔬菜切碎作为酱汁。然后,你开始煮酱汁,同时偶尔检查一下肉。在这里,两项任务(烤肉和制作酱汁)都在进行中,但您正在它们之间切换注意力。这代表并发。

并行示例:

现在,假设您有一位朋友可以帮助您。当您专注于烤肉时,您的朋友则负责制作酱汁。这两项任务同时完成,无需在它们之间切换注意力。这代表并行性。

什么是异步编程?

异步编程涉及处理程序外部发生的输入/输出(i/o)操作,例如用户输入、打印到终端、从套接字读取或写入磁盘。异步 i/o 的关键特征是:

  • 操作所花费的时间与cpu无关。相反,它取决于磁盘速度、网络延迟和其他外部条件等因素。

  • 程序无法预测操作何时结束。

对于具有大量 i/o 的服务(如 web 服务器、数据库和部署脚本),优化这些操作可以极大地提高性能。

让我们看看阻塞代码和非阻塞代码的示例。

阻塞和非阻塞代码示例

考虑一个简单的程序:

import time

def task():
    time.sleep(2)
    print("hello")

for _ in range(3):
    task()

在这个同步程序中,每个任务都会等待前一个任务完成,从而导致延迟。

现在,让我们看一下使用 asyncio 的异步版本:

import asyncio

async def task():
    await asyncio.sleep(2)
    print("hello")

async def main():
    tasks = [task() for _ in range(3)]
    await asyncio.gather(*tasks)

asyncio.run(main())

在这个异步程序中,任务同时运行,减少了总执行时间。让我们探索异步编程的组件。

异步编程的组成部分

事件循环、协程和 future 是异步 python 程序的基本元素。

  • 事件循环:管理任务切换和执行流程,跟踪要异步运行的任务。

  • 协程: 可以暂停和恢复的特殊功能,允许在等待期间运行其他任务。协程指定任务切换事件应在函数中发生的位置,将控制权返回给事件循环。协程通常由事件循环创建并内部存储在任务队列中。

  • futures: 协程结果的占位符,存储结果或异常。一旦事件循环启动一个协程,就会创建一个相应的 future 来存储协程的结果,如果在协程执行过程中抛出异常,则会创建一个异常。

解释完 python 异步编程的关键部分后,让我们编写一些代码。

编写异步代码

现在您已经了解了异步编程模式,让我们编写一个小脚本并分析执行情况。这是一个简单的异步脚本:

import asyncio

async def task():
    await asyncio.sleep(2)
    print("hello")

async def main():
    tasks = [task() for _ in range(3)]
    await asyncio.gather(*tasks)

asyncio.run(main())

在上面的代码中,我们尝试继续执行其他任务,即使另一个正在执行的任务正在睡眠(阻塞)。注意任务和主要函数前面的 async 关键字。

这些函数现在是协程.

python 中的协程函数前面有关键字 async。这里的 main() 函数是任务协调器或我们的单个事件循环,因为它使用 async.gather 方法执行所有任务。 asyncio.gather 函数同时运行可等待对象。

输出:

腾讯交互翻译
腾讯交互翻译

腾讯AI Lab发布的一款AI辅助翻译产品

下载
hello
hello
hello
program executed in 2.01 seconds.

当每个任务到达await asyncio.sleep(2)时,它只是转到下一个任务并在完成时返回。这就像在说:“我要睡 2 秒钟。做点别的事吧。”

让我们看看同步版本,以便快速比较。

import time

def task():
    time.sleep(2)
    print("hello")

for _ in range(3):
    task()

在上面的代码中,我们采用传统的python编程方式。您会注意到该过程的执行将花费更多时间。

输出:

hello
hello
hello
program executed in 6.01 seconds.

现在你可以注意到执行时间了。将 time.sleep() 视为阻塞任务,将 asyncio.sleep() 视为非阻塞或长时间任务。在异步编程中,等待某些内容(例如 asyncio.sleep())的好处是,周围的函数可以暂时将控制权交给另一个准备立即执行的函数。

了解了 python 异步编程的一些基本示例后,让我们来探索一下 python 异步编程的规则。

异步编程规则

  1. 协程:协程不能直接执行。如果您尝试直接运行协程函数,它将返回一个协程对象。相反,使用 asyncio.run():

    import asyncio
    
    async def hello():
        await asyncio.sleep(1)
        print('hello')
    
    asyncio.run(hello())
    
  2. 可等待对象: 协程、futures 和任务是主要的可等待对象。 python 协程是可等待的,并且可以被其他协程等待。

  3. await 关键字:await 只能在异步函数中使用。

    async def hello():
        await asyncio.sleep(1)
        print("hello")
    
  4. 兼容性: 并非所有 python 模块都兼容异步编程。例如,将await asyncio.sleep() 替换为time.sleep() 将导致错误。您可以在这里查看兼容和维护的模块列表。

在下一节中,我们将探讨异步编程的常见用法,http 请求。

程序示例:异步请求

我们来看看下面这段代码:

import aiohttp
import asyncio

async def fetch(session, city):
    url = f"https://www.prevision-meteo.ch/services/json/{city}"
    async with session.get(url) as response:
        data = await response.json()
        print(f"temperature at {city}: {data['current_condition']['tmp']} c")

async def main():
    async with aiohttp.clientsession() as session:
        cities = ['paris', 'toulouse', 'marseille']
        tasks = [fetch(session, city) for city in cities]
        await asyncio.gather(*tasks)

asyncio.run(main())

在上面的代码中,我们创建了两个异步函数:一个用于从 prevision-meteo url 获取数据,另一个主函数用于执行 python 代码中的进程。目标是发送异步 http get 请求来检索温度并打印响应。

在main和fetch函数中,我们使用了async with。在 fetch 函数中,async with 确保连接正确关闭。在 main 函数中,它确保 clientsession 在完成请求后关闭。这些实践对于 python 异步编码中有效管理资源并防止泄漏非常重要。

在main函数的最后一行,我们使用await asyncio.gather(*tasks)。在我们的例子中,它同时运行所有任务,允许程序同时发送多个 http 请求。使用await可确保程序等待所有任务完成后再继续。

输出:

temperature at marseille: 25 c
temperature at toulouse: 24 c
temperature at paris: 18 c
program executed in 5.86 seconds.

用于比较的同步版本

代码:

import requests
import time

def fetch(city):
    url = f"https://www.prevision-meteo.ch/services/json/{city}"
    response = requests.get(url)
    data = response.json()
    print(f"temperature at {city}: {data['current_condition']['tmp']} c")

def main():
    cities = ['paris', 'toulouse', 'marseille']
    for city in cities:
        fetch(city)

start_time = time.time()
main()
print(f"program executed in {time.time() - start_time:.2f} seconds.")

输出:

Temperature at Paris: 18 C
Temperature at Toulouse: 24 C
Temperature at Marseille: 25 C
Program executed in 9.01 seconds.

何时使用异步编程

异步模型在以下情况下表现最佳:

  • 任务数量较多,保证至少有一个任务可以一直进行。

  • 任务涉及大量 i/o,导致异步程序在其他任务可以运行时浪费大量时间阻塞。

  • 任务在很大程度上是独立的,最大限度地减少任务间通信(从而使一个任务等待另一任务)。

结论

在本教程中,我们介绍了:

  • 异步编程的概念及相关概念。

  • 有效使用async/await。

  • 使用 aiohttp 发出异步 http 请求。

  • 异步编程的好处。

感谢您的阅读。第二部分将介绍 django 的异步编程。

资源

  • python 文档:协程和任务

  • python 文档:asyncio - 异步 i/o

  • aiohttp 文档

  • aio 图书馆

  • 并发与并行

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python Web 框架 Django 深度开发
Python Web 框架 Django 深度开发

本专题系统讲解 Python Django 框架的核心功能与进阶开发技巧,包括 Django 项目结构、数据库模型与迁移、视图与模板渲染、表单与认证管理、RESTful API 开发、Django 中间件与缓存优化、部署与性能调优。通过实战案例,帮助学习者掌握 使用 Django 快速构建功能全面的 Web 应用与全栈开发能力。

166

2026.02.04

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

497

2023.08.14

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

385

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2111

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

357

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

259

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

329

2023.10.09

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

420

2023.10.16

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 4.9万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号