Python使用Asyncio进行web编程方法详解
作者:宇宙之一粟 发布时间:2022-08-11 17:03:56
前言
许多 Web 应用依赖大量的 I/O (输入/输出) 操作,比如从网站上下载图片、视频等内容;进行网络聊天或者针对后台数据库进行多次查询。数据库查询可能会耗费大量时间,尤其是在该数据库处于高负载或查询很复杂的情况下。 Web 服务器可能需要同时处理数百或数千个请求。
I/O 是指计算机的输入和输出设备,例如键盘、硬盘驱动器,以及最常见的网卡。这些操作等待用户输入或从基于 Web 的 API 检索内容。
Asynchronous IO (async IO) 是一种异步编程设计,并在 Python 3.4 的 asyncio
模块中得到了支持,作为在多线程和多进程之外处理这些高并发工作负载的另一种方法,可以显着提高使用 I/O 操作的应用程序的性能和资源利用率。
什么是同步编程
同步编程,通常来说,大多数编程语言都是子例程调用模型:按照顺序运行代码。在此模型中,下一行代码在前一行代码完成后立即运行,并且一次只完成一个模块。
该模型适用于大部分应用程序。但是,也存在明显的缺点,如果一行代码特别慢怎么办?
在这种情况下,速度慢的代码将导致所有其他代码都将被卡住,直到该行完成。最差的情况下可能导致整个应用程序卡死。可能大多数人在某些软件操作中,一个小小的操作导致整个系统执行不下去,最后只能重启。
什么是异步编程
为了解决同步模型的问题,引入了异步编程的概念,意味着允许同一时刻执行多个任务。
异步编程模型意味着需要长时间运行的任务可以在后台运行,与主应用程序分开。系统可以自由地执行不依赖于该任务的其他工作,而不是阻止所有其他应用程序代码等待该长时间运行的任务完成。然后,一旦长时间运行的任务完成,我们会收到通知它已完成。
asyncio 库允许我们使用异步编程模型运行代码。 这让我们可以一次处理多个 I/O 操作,同时仍然允许我们的应用程序保持响应。
在 Python 3.4 中,asyncio 库中包含了装饰器和生成器 yield from
来定义协程(coroutine)。协程是一种方法,当我们有一个可能长时间运行的任务时可以暂停,然后在该任务完成时恢复。
协程执行完成后返回到调用者有一种新方法:通过 yield
控制。当协程的 yield
执行完成后立即回到了调用点,但是对协程的再次调用不会在起始处再次开始,相反,他们继续从最近停止处继续进行。
如下图所示:
def filter_even(numbers):
for num in range(numbers):
if (num % 2 == 0):
yield num
even_number = filter_even(100)
print(list(even_number))
运行结果:
$ python yielddemo.py
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98]
ayncio 版 Hello 程序
Python 3.5 版中,当关键字 async 和 await 显式添加到语言中时,该语言实现了对协程和异步编程的一流支持。 这种语法在 C# 和 JavaScript 等其他编程语言中很常见,它允许我们使异步代码看起来像是同步运行的。 这使得异步代码易于阅读和理解,因为它看起来像大多数软件工程师熟悉的顺序流程。 asyncio 是一个使用称为单线程事件循环的并发模型以异步方式执行这些协程的库。
利用 async
/await
两个定义关键字定义协程,通过 asyncio
提供运行和管理协程的基础:
import asyncio
import time
async def main():
print(f'{time.ctime()} Hello!')
await asyncio.sleep(1.0)
print(f'{time.ctime()} See you again!')
asyncio.run(main())
运行结果:
$ python asynciodemo.py
Sat Jul 9 23:19:40 2022 Hello!
Sat Jul 9 23:19:41 2022 See you again!
asyncio
提供了一个 run()
函数来执行 async def
函数,然后从那里调用的所有其他协程,如 main()
函数中的 sleep()
函数。asyncio
不是多线程或多进程,而是并行运行代码。
JavaScript 中支持异步执行(浏览器,Nodejs,Electron 等)。在早期版本中,他们只是使用回调功能在异步操作完成后运行其他功能。
如何使用 asyncio
创建协程很简单,与创建普通的 Python 函数没有太大区别。唯一的区别是,我们不是使用 def
关键字,而是 使用 async def
。async 关键字将函数标记为协程,而不是普通的 Python 函数。
import asyncio
import time
def write(msg):
print(msg, flush=True)
async def say1():
await asyncio.sleep(1)
write("Hello from 1")
async def say2():
await asyncio.sleep(1)
write("Hello from 2")
write("start")
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(
say1(),
say2()
))
write("exit")
loop.close()
运行该代码,可以看到 Hello from 1
运行 1 秒后运行 Hello from 2
:
$ python asyncoidemo2.py
start
Hello from 1
Hello from 2
exit
当 run_until_complete
运行 say()
函数,解释器会逐行执行该函数的内容。当碰到 await
之后,解释器开始异步操作:这个操作为了循环将完成一些内部回调操作,这个回调操作是对开发人员隐藏的。但是现在,say1
开始后,它立即将控制返回到事件循环。所以,它启动异步 sleep
和控制循环,然后循环实际上已经开始启动 say2
函数。
当第一次异步 sleep
运行 1秒后,进入内部回调执行 say1
协程,下一个操作是打印 Hello from 1
。打印后,它再次返回到活动循环。同时,从第二次睡眠开始,循环获得了有关完成第二次睡眠的事件。
所以接下来 Hello from 2
打印,然后第二种方法也返回。
run_until_complete(gather(l1,l2,l3))
将阻止所有 l1,l2,l3 Coroutines:
请注意,7 和 9 事件可能会交换 - 如果您多次运行代码,您可能会注意到 Hello from 1 打印在 Hello from 2 之后。
event_loop 事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数
coroutine 协程:协程对象,指一个使用
async
关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态
future: 代表将来执行或没有执行的任务的结果。它和 task 上没有本质上的区别
async/await 关键字:python3.5 用于定义协程的关键字,
async
定义一个协程,await
用于挂起阻塞的异步调用接口。
来源:https://juejin.cn/post/7122764568547786783
猜你喜欢
- VueX浏览器刷新保存数据在vue项目中用vuex来做全局的状态管理, 发现当刷新网页后,保存在vuex实例store里的数据会丢失。原因:
- 例1:#!/usr/bin/perluse strict; use warnings;my $test = "asdf"
- DBScan 算法解释说明DBScan 是密度基于空间聚类,它是一种基于密度的聚类算法,其与其他聚类算法(如K-Means)不同的是,它不需
- 本文实例讲述了Python处理XML格式数据的方法。分享给大家供大家参考,具体如下:这里的操作是基于Python3平台。在使用Python处
- 首先祝贺Echarts顺利的从Apache毕业,多了个响亮的名字:Apache ECharts,现在的官网地址在这里:传送门,首页相当的国际
- 本文通过调取高德行政区划查询接口,获取最新的数据信息(省、市、区、经纬度、行政级别、城市编码、行政编码等),并通过mysql.connect
- 寒假里学习了一下Python爬虫,使用最简单的方法扒取需要的天气数据,对,没听错,最简单的方法。甚至没有一个函数封装。。网址:http://
- 在二维矩阵间的运算:class torch.nn.Conv2d(in_channels, out_channels, kernel_size
- 一、什么是用户体验?用户体验的名词解释用户体验(User Experience,简称UE)是一种纯主观的在用户使用一个产品(服务)的过程中建
- 特征选择时困难耗时的,也需要对需求的理解和专业知识的掌握。在机器学习的应用开发中,最基础的是特征工程。——吴恩达1.数据预处理数据预处理需要
- 要想成功的进行字符串的匹配需要使用到正则表达式模块,正则表达式匹配规则以及需要被匹配的字符串。在这三个条件中,模块与字符串都是准备好的,只有
- 本文实例讲述了Python使用matplotlib和pandas实现的画图操作。分享给大家供大家参考,具体如下:画图在工作再所难免,尤其在做
- 之前有教大家制作日历,很多小伙伴都兴奋的告诉小编自己成功了。那么我们在日历中怎么去找到我们想要的那个时间点呢?其实有点类似于查询的功能,但是
- 在NLP中,数据清洗与分词往往是很多工作开始的第一步,大多数工作中只有中文语料数据需要进行分词,现有的分词工具也已经有了很多了,这里就不再多
- 双向RNN:bidirectional_dynamic_rnn()函数的使用详解先说下为什么要使用到双向RNN,在读一篇文章的时候,上文提到
- 本文将介绍如何基于Python Django实现验证码登录功能。验证码登录是一种常见的身份验证方式,它可以有效防止恶意攻击和机器人登录。本文
- shp2sqlserver用法简析 官方说明: shp2sqlserver is a command line tool for loadi
- 1.简介MongoDB是一个基于分布式文件存储的文档数据库,可以说是非关系型(NoSQL,Not Only SQL)数据库中比较像关系型数据
- gitee的指定分支想上传的本地文件夹为C#learning下面为使用git将这个C#learning上传到项目的example的方法1.在
- 在js中直接添加html语句,js会将html字符串解析成相应的HTML语句,并在前端进行显示。 <span style="