异步编程和asyncio

        介绍异步编程的重要性和在Python中的应用,特别是在I/O密集型任务和网络编程场景下。

目录

理解异步编程

异步编程基本概念

任务与Future

异步编程的工作原理

事件循环

协程(Coroutines)

异步与同步代码的结合

深入asyncio模块

事件循环(Event Loop)

协程(Coroutines)

使用async和await

任务(Tasks)

异步I/O和网络操作

异步编程实战

1. 异步HTTP请求

2. 异步文件操作

3. 异步数据库操作

4. 异步Web服务器


理解异步编程

        异步编程是一种编程范式,它允许程序在等待某些操作完成时继续执行其他任务,而不是阻塞等待。这在处理I/O密集型任务(如网络请求、文件读写等)时尤其有用,因为这些操作的延迟往往不可预测且很难避免。

异步编程基本概念

异步编程允许程序在等待操作完成时继续执行其他任务,这在处理I/O密集型操作时尤其有用。

# 异步函数示例
import asyncioasync def hello_world():print("Hello, world!")# 运行事件循环,直到hello_world()协程执行完成
asyncio.run(hello_world())

在这个例子中,hello_world是一个异步函数,使用async def定义。asyncio.run(hello_world())运行事件循环,执行hello_world协程。

任务与Future

任务是对协程的进一步抽象,它们在事件循环中被调度。asyncio.gather可以并发运行多个任务。

async def count():print("One")await asyncio.sleep(1)print("Two")async def main():# 创建并同时运行两个count()协程await asyncio.gather(count(), count())asyncio.run(main())

异步编程的工作原理

        在同步编程中,如果一个函数需要等待某个操作完成(比如,等待网络响应),它会阻塞程序的执行,直到操作完成。而在异步编程中,当遇到这种等待情况时,程序可以“挂起”当前任务,并开始执行另一个任务,直到原任务的等待操作完成,然后再回来继续执行。

        这种方式依赖于事件循环(Event Loop),它是异步编程的核心。事件循环不断检查是否有任务完成了等待的操作,如果有,则将这些任务重新加入到任务队列中继续执行。

事件循环

        事件循环是异步编程中管理和调度任务执行的机制。在Python的asyncio模块中,事件循环的概念是通过事件循环对象来实现的。

import asyncio# 获取当前事件循环
loop = asyncio.get_event_loop()# 事件循环:运行直到某个任务完成
loop.run_until_complete(async_function())# 关闭事件循环
loop.close()

        在这个例子中,async_function()代表了一个异步函数,它可能包含了诸如网络请求等需要等待的操作。run_until_complete()方法会运行事件循环,直到传入的协程执行完成。

协程(Coroutines)

        协程是Python中实现异步编程的关键。在Python中,协程是一种特殊类型的函数,它的定义使用async def语法。协程内部可以使用await关键字挂起协程的执行,等待异步操作完成。

async def async_function():# 模拟异步操作,比如网络请求await asyncio.sleep(1)print("异步操作完成")# 运行协程
asyncio.run(async_function())

        在async_function中,await asyncio.sleep(1)模拟了一个异步操作。await关键字使得协程的执行在这里暂停,让出控制权给事件循环,直到asyncio.sleep(1)完成,协程才会继续执行。

异步与同步代码的结合

        在实际应用中,异步代码经常需要与同步代码相结合。asyncio提供了多种机制来支持这种结合,如run_in_executor方法,它可以用于在事件循环中执行同步代码。

def sync_function():# 模拟耗时的同步操作time.sleep(1)print("同步操作完成")async def main():loop = asyncio.get_running_loop()# 在事件循环中运行同步函数await loop.run_in_executor(None, sync_function)# 运行主协程
asyncio.run(main())

        这个例子展示了如何在异步程序中运行同步代码。run_in_executor方法允许将同步函数sync_function在事件循环中作为异步任务执行,从而避免阻塞事件循环。

        通过这种方式,异步编程模型允许你构建出响应更快、性能更高的应用,特别是在处理大量I/O操作时。在下一章中,我们将深入探讨asyncio模块,了解其提供的工具和机制,以及如何使用它们来构建高效的异步应用。

深入asyncio模块

        asyncio是Python标准库的一部分,提供了编写单线程并发代码的基础设施,特别适用于I/O密集型任务。它使用async/await语法,是实现异步编程的主要方法之一。

事件循环(Event Loop)

        事件循环是asyncio中的核心概念,负责管理和分发事件。所有的异步操作都是在事件循环中执行的。

import asyncioasync def main():print('Hello')await asyncio.sleep(1)print('World')# asyncio.run() 是 Python 3.7+ 中引入的简化事件循环管理的函数
asyncio.run(main())

        在这个例子中,asyncio.run(main())启动了事件循环,运行main()协程。await asyncio.sleep(1)会暂停main()协程的执行,让出控制权给事件循环,直到延时完成。

协程(Coroutines)

        协程是通过async def定义的异步函数。在协程内部,可以使用await来挂起协程的执行,等待另一个协程完成。

async def fetch_data():print("Start fetching")await asyncio.sleep(2)  # 模拟I/O操作print("Data fetched")return {'data': 1}async def print_numbers():for i in range(10):print(i)await asyncio.sleep(0.25)async def main():task1 = asyncio.create_task(fetch_data())task2 = asyncio.create_task(print_numbers())# 等待两个协程任务完成await task1await task2asyncio.run(main())

fetch_dataprint_numbers是通过async def定义的协程。asyncio.create_task()用于并发运行这两个协程。这里,fetch_data模拟了异步的I/O操作,而print_numbers则在这个操作进行时并发运行。

使用asyncawait

  asyncawait是异步编程的核心,async将函数声明为协程函数,await用于挂起协程的执行,等待异步操作完成。

async def compute(x, y):print("Compute %s + %s ..." % (x, y))await asyncio.sleep(1.0)return x + yasync def main():result = await compute(1, 2)print("Result:", result)asyncio.run(main())

        这个例子中,compute协程在执行过程中使用await asyncio.sleep(1.0)挂起,模拟了一个耗时的计算操作。main协程等待compute的结果,然后打印。

任务(Tasks)

任务用于并发调度协程,是对协程的一种封装。

async def task_func():print('Task start')await asyncio.sleep(1)  # 模拟I/O操作print('Task finished')async def main():task = asyncio.create_task(task_func())await task  # 等待任务完成asyncio.run(main())

在这个例子中,asyncio.create_task()创建了一个任务,这个任务包装了task_func协程。await task会等待任务完成,这期间事件循环可以运行其他任务或协程。

异步I/O和网络操作

asyncio提供了一套用于执行异步网络操作的高级API,如asyncio.open_connection用于TCP连接。

async def tcp_echo_client(message):reader, writer = await asyncio.open_connection('127.0.0.1', 8888)print(f'Send: {message}')writer.write(message.encode())await writer.drain()data = await reader.read(100)print(f'Received: {data.decode()}')writer.close()await writer.wait_closed()asyncio.run(tcp_echo_client('Hello World!'))

异步编程实战

在本章中,我们将探索如何将asyncio应用于实际场景中,通过具体的示例展示异步编程的强大功能和高效性。

1. 异步HTTP请求

在进行网络请求时,异步编程能显著提高性能。以下示例展示了如何使用aiohttp库执行异步HTTP请求:

import aiohttp
import asyncioasync def fetch_url(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_url(session, 'https://www.example.com')print(html[:100])  # 打印获取到的HTML内容的前100个字符asyncio.run(main())

2. 异步文件操作

异步文件操作可以提高I/O密集型应用的性能。以下示例展示了如何使用aiofiles库进行异步文件读写操作:

import aiofiles
import asyncioasync def write_to_file(filename, content):async with aiofiles.open(filename, 'w') as f:await f.write(content)async def read_from_file(filename):async with aiofiles.open(filename, 'r') as f:content = await f.read()return contentasync def main():await write_to_file('example.txt', 'Hello, asyncio!')content = await read_from_file('example.txt')print(content)asyncio.run(main())

3. 异步数据库操作

数据库操作是另一个适合应用异步编程的场景。以下示例使用aiomysql库进行异步数据库操作:

import aiomysql
import asyncioasync def fetch_data(loop):conn = await aiomysql.connect(host='127.0.0.1', port=3306,user='root', password='password',db='test_db', loop=loop)async with conn.cursor() as cur:await cur.execute("SELECT 42;")(result,) = await cur.fetchone()print("Result:", result)conn.close()loop = asyncio.get_event_loop()
loop.run_until_complete(fetch_data(loop))

4. 异步Web服务器

使用aiohttp库,你还可以构建一个简单的异步Web服务器:

from aiohttp import web
import asyncioasync def handle(request):return web.Response(text="Hello, asyncio!")app = web.Application()
app.add_routes([web.get('/', handle)])web.run_app(app)

        通过本文的深入解读,我们已经对Python中的异步编程有了全面的了解。从基础的async和await,到asyncio模块的高级应用,我们学习了如何利用这些强大的工具来提升程序的性能和响应速度。实际应用案例展示了异步编程在处理网络请求、文件I/O和数据库操作中的高效性。随着技术的不断进步,异步编程将在未来的软件开发中扮演越来越重要的角色。希望本文能够为你在这个领域的探索提供有价值的指南和灵感。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/737876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CCF-C推荐会议 IEEE CLOUD‘24 3月24日截稿!深圳开启全球云计算新纪元!

会议之眼 快讯 IEEE CLOUD(IEEE International Conference on Cloud Computing)即IEEE云计算国际会议将于 2024 年7月7日至13日在中国深圳举行!IEEE CLOUD由lEEE Computer Society主办,CCF服务计算专委会、北京大学、IBM Research承办。CLOUD一直是研究人…

软件测试APP完整测试作业流程(附流程图),公司级软件测试流程化办公

目录 1. 概述 2. 软件测试流程 3. 软件测试周期人员活动图 4. 总结 1. 概述 1.1 目的 有效的保证软件质量; 有效的制定不同测试类型(软件系统测试、音频主观性测试、Field Trial、专项测试、自动化测试、性 能测试、用户体验测试)的软件…

【框架设计】MVC和MVVM对比图

1. MVC(Model-View-Controller) 单向通信View和Model通过Controller承上启下 2. MVVM(Model-View-ViewModel) 数据绑定M -> VM -> V DOM事件监听 V -> VM -> M 1. MVC是单向的,MVVM是双向的,…

【SpringCloud微服务全家桶学习笔记-GateWay网关(微服务入口)】

Gateway服务网关 API网关为微服务架构中的服务提供了统一的访问入口,客户端通过API网关访问相关服务。API网关的定义类似于设计模式中的门面模式,它相当于整个微服务架构中的门面,所有客户端的访问都通过它来进行路由及过滤。它实现了请求路…

二 超级数据查看器   讲解稿   导入功能

二 超级数据查看器 讲解稿 导入功能 APP下载地址 百度手机助手 下载地址4 ​ 讲解稿全文: 大家好。 今天我们对 超级数据查看器的 导入信息功能 做一下详细讲解。 首先,我们打开 超级数据查看器。 我们这个系统要实现的是,快速生…

GEE:基于Landsat8计算陆地表面温度(Land Surface Temperature,LST)

作者:CSDN _养乐多_ 本文将介绍在Google Earth Engine(GEE)平台上使用 Landsat 8 卫星影像数据计算陆地表面温度(Land Surface Temperature,LST)的代码。 结果如下图所示, 文章目录 一、参考…

阿里P8解析自动化测试工具 —— SeleniumAppium!

自动化测试,利用自动化测试工具,通过录制/编程方式实现测试活动,发现被测对象存在的缺陷,从而替代手工测试活动。自动化测试不局限于某个具体测试阶段,也不局限被测对象的类型,只要满足自动化测试的必要条件…

数据库--SQL语言-1

练习网站:自学SQL网 Select 查询语法复习 SELECT column, another_column, …FROM mytableWHERE condition AND/OR another_condition AND/OR …; 操作符号: 如果属性是字符串, 我们会用到字符串相关的一些操作符号,其中 LIKE&#xff08…

day04-Maven-SpringBootWeb入门

文章目录 01. Maven1.1 课程安排1.2 什么是Maven1.3 Maven的作用1.4 Maven模型1.5 Maven仓库1.6 Maven安装1.6.1 下载1.6.2 安装步骤 2 IDEA集成Maven2.1 配置Maven环境2.1.1 当前工程设置2.1.2 全局设置 2.2 创建Maven项目2.3 POM配置详解2.4 Maven坐标详解2.5 导入Maven项目 …

【axios】你的进度条准确吗

1、axios监听进度 上传和下载操作在前端中是非常常见的,当我们想知道上传或下载的进度时也不难,axios已经实现了监听进度的方法 import axios from axios// 上传请求 axios.post(/api/v1/upload, {data: xxx},{// onUploadProgress回调可以获取进度onU…

mysql 常用命令

1、显示锁的时间 show status like innodb_row_lock%;2、锁一行的方法 //开启 begin; //锁一行 select * from tbl_user where name 1aa1 for update;//解锁 commit;3、设置不自动提交 set autocommit 0; //自动提交 set autocommit 1;4、查看是否支持profile show vari…

2 月 Web3 游戏行业动态

作者:stellafootprint.network 数据来源:区块链游戏研究页面 - Footprint Analytics 2024 年 2 月,区块链游戏领域在加密货币价格上涨和活跃用户激增的推动下,实现了显著增长。然而,行业在维持用户参与度和留存率方面…

NodeJS实现线性查找算法

NodeJS实现线性查找算法 以下是使用 Node.js 实现线性搜索算法的示例代码&#xff1a; function linearSearch(arr, target) {for (let i 0; i < arr.length; i) {if (arr[i] target) {return i; // 如果找到目标&#xff0c;返回索引}}return -1; // 如果未找到目标&am…

微服务配置中心

什么是配置中心 配置中心是一种用于管理应用程序或系统配置信息的中央服务。它允许开发人员在多个环境&#xff08;如开发、测试、生产&#xff09;之间共享配置&#xff0c;并且可以在不停止应用程序的情况下动态更新配置。 配置中心是统一管理各种应用配置的工具。它能够集中…

【Ubuntu】原生Ubuntu-dock 栏 安装与卸载

1.查看是否安装 Ubuntu-dock&#xff08;新版本的Ubuntu自带Ubuntu-dock version> 18.04&#xff09; gnome-extensions list 2.安装Ubuntu-dock sudo apt install gnome-shell-extension-ubuntu-dock 3.重启&#xff0c;一定要重启&#xff01;&#xff01;&#xff01;…

LeetCode2.07链表相交

2.07链表相交 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返回结…

vue实现图片框选标注

前言 前端有一个需求&#xff0c;对上传的图片进行检测识别&#xff0c;通过返回的接口坐标数据&#xff0c;对图片的某些区域进行框选并标注。如图&#xff1a; 开始 1、上传功能使用elementui的upload插件&#xff1b; 2、在图片上进行标注功能是元素定位在图片上层&#x…

Java - 探究Java优雅退出的两种机制

文章目录 概述Java优雅停机_ ShutdownHook 机制步骤Code Java优雅停机_ 信号量机制SignalHandler 工作原理使用步骤Linux支持的信号量根据操作系统选择信号量Code 注意事项 概述 在Linux上通过kill -9 pid方式强制终止进程的副作用&#xff0c;这种方式虽然简单高效&#xff0…

小红书素人投放计划怎么做?

小红书素人投放是很多品牌在小红书推广打响的第一枪&#xff0c;素人铺量在小红书投放&#xff0c;可以奠定品牌在小红书的声量&#xff0c;小红书素人投放计划怎么做&#xff1f;前期规划好一切&#xff0c;才能在后期让我们的推广爆发出更好的效果。接下来伯乐网络传媒就来给…

【压缩包技巧】如何把rar文件压缩为zip格式?

想要将rar文件压缩为zip格式&#xff0c;其实就是压缩包格式进行转换&#xff0c;今天和大家分享三个rar压缩包改成zip格式的方法&#xff0c;希望能够帮助到大家&#xff01; 方法一&#xff1a; 直接修改rar压缩包的后缀名变为zip&#xff0c;就可以修改压缩包文件格式了 …