我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python中asyncio异步编程的示例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python中asyncio异步编程的示例分析

这篇文章将为大家详细讲解有关python中asyncio异步编程的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

1.   想学asyncio,得先了解协程

携程的意义:

  1. 计算型的操作,利用协程来回切换执行,没有任何意义,来回切换并保存状态 反倒会降低性能。

  2. IO型的操作,利用协程在IO等待时间就去切换执行其他任务,当IO操作结束后再自动回调,那么就会大大节省资源并提供性能,从而实现异步编程(不等待任务结束就可以去执行其他代码

2.协程和多线程之间的共同点和区别:

共同点:

都是并发操作,多线程同一时间点只能有一个线程在执行,协程同一时间点只能有一个任务在执行;

不同点:

多线程,是在I/O阻塞时通过切换线程来达到并发的效果,在什么情况下做线程切换是由操作系统来决定的,开发者不用操心,但会造成竞争条件 (race condition) ;

协程,只有一个线程,在I/O阻塞时通过在线程内切换任务来达到并发的效果,在什么情况下做任务切换是开发者决定的,不会有竞争条件 (race condition) 的情况;多线程的线程切换比协程的任务切换开销更大;
对于开发者而言,多线程并发的代码比协程并发的更容易书写。

一般情况下协程并发的处理效率比多线程并发更高。

3. greenlet实现协程

greenlet用于创建协程,switch用于进行协程之间的切换某个协程在执行的过程中可以随时的被其他协程通过switch函数来打断,转而去执行其他协程,当前协程的中断现场会被保留,一旦中断的协程再次获得cpu的执行权首先会恢复现场然后从中断处继续执行这种机制下的协程是同步,不能并发

pip install greenlet

import timeimport greenlet  def func1():  print("func11")  gr2.switch()  time.sleep(1)  print("func22")  gr2.switch()  def func2():  print("func33")  gr1.switch()  time.sleep(1)  print("func44")  start = time.time()gr1 = greenlet.greenlet(func1)gr2 = greenlet.greenlet(func2)gr1.switch()end = time.time()print(end - start)

4. yield关键字实现协程

def func1():  yield 1  yield from func2()  yield 3  def func2():  yield 2  yield 4  ff = func1()for item in ff:  print(item)

5.gevent协程

(1)gevent实现协程

pip install gevent

from greenlet import greenletfrom time import sleepdef func1():  print("协程1")  sleep(2)  g2.switch()  print("协程1恢复运行") def func2():  print("协程2")  sleep(1)  g3.switch()def func3():  print("协程3")  sleep(1)  g1.switch() if __name__ == '__main__':  # 使用greenlet来创建三个协程  g1 = greenlet(func1)  g2 = greenlet(func2)  g3 = greenlet(func3)  # print(g1)  g1.switch() # 让协程g1取抢占cpu资源

(2) gevent实现异步协程

# 协程被创建出来以后默认是多个协程同步执行# 我们可以加入monkey补丁,把同步的协程转成异步协程from gevent import monkey # 注意:monkey的引入必须在其他模块之前 monkey.patch_all() # 用monkey给整个协程队列,添加一个非阻塞I/O的补丁,使得他们成为异步协程import timeimport requestsimport gevent headers = {  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}  def func(url, i):  print("协程%d开启!" % i)  res = requests.get(url=url, headers=headers)  html = res.text  print("协程%d执行结束,获取到的响应体大小为:%d" % (i, len(html)))  if __name__ == '__main__':  start = time.time()  urls = [    "https://www.baidu.com/",    "https://www.qq.com/",    "https://www.sina.com.cn",    "https://www.ifeng.com/",    "https://www.163.com/"  ]  # 创建5个协程分别对上面5个网站进行访问  g_list = []  for i in range(len(urls)):    g = gevent.spawn(func, urls[i], i)    g_list.append(g)    # func(urls[i], i)  gevent.joinall(g_list)  end = time.time()  print(end - start)

6. asyncio模块实现异步协程

在python3.4及之后的版本使用,asyncio厉害之处在于:遇到IO操作时会自动切换执行其它任务

import timeimport asyncio  @asyncio.coroutinedef func1():  print(1)  yield from asyncio.sleep(1) # 遇到IO耗时操作,自动切换到tasks中的其它任务  print(2)  @asyncio.coroutinedef func2():  print(3)  yield from asyncio.sleep(1) # 遇到IO耗时操作,自动切换到tasks中的其它任务  print(4)  tasks = [  asyncio.ensure_future(func1()),  asyncio.ensure_future(func2())] start = time.time()loop = asyncio.get_event_loop()loop.run_until_complete(asyncio.wait(tasks))end = time.time()print(end - start)

7. asyc & await关键字实现异步编程(现在推荐使用的用法)

在python3.5及之后的版本中可以使用

import timeimport asyncio  async def func1():  print(1)  await asyncio.sleep(1)  print(2)  async def func2():  print(3)  await asyncio.sleep(1)  print(4)  tasks = [  asyncio.ensure_future(func1()),  asyncio.ensure_future(func2())] start = time.time()loop = asyncio.get_event_loop()loop.run_until_complete(asyncio.wait(tasks))end = time.time()print(end - start)

7.1 事件循环

    事件循环,可以把他当做是一个while循环,这个while循环在周期性的运行并执行一些任务,在特定条件下终止循环。

伪代码:

# 伪代码任务列表 = [ 任务1, 任务2, 任务3,... ]while True:  可执行的任务列表,已完成的任务列表 = 去任务列表中检查所有的任务,将'可执行'和'已完成'的任务返回  for 就绪任务 in 已准备就绪的任务列表:    执行已就绪的任务  for 已完成的任务 in 已完成的任务列表:    在任务列表中移除 已完成的任务  如果 任务列表 中的任务都已完成,则终止循环

7.2 协程和异步编程

协程函数,定义形式为 async def 的函数。

协程对象,调用 协程函数 所返回的对象。

# 定义一个协程函数async def func():  pass# 调用协程函数,返回一个协程对象result = func()

注意:调用协程函数时,函数内部代码不会执行,只是会返回一个协程对象。 

7.3 基本应用

程序中,如果想要执行协程函数的内部代码,需要 事件循环 和 协程对象 配合才能实现,如:

import asyncioasync def func():  print("协程内部代码")# 调用协程函数,返回一个协程对象。result = func()# 方式一# loop = asyncio.get_event_loop() # 创建一个事件循环# loop.run_until_complete(result) # 将协程当做任务提交到事件循环的任务列表中,协程执行完成之后终止。# 方式二# 本质上方式一是一样的,内部先 创建事件循环 然后执行 run_until_complete,一个简便的写法。# asyncio.run 函数在 Python 3.7 中加入 asyncio 模块,asyncio.run(result)

这个过程可以简单理解为:将协程当做任务添加到 事件循环 的任务列表,然后事件循环检测列表中的协程是否 已准备就绪(默认可理解为就绪状态),如果准备就绪则执行其内部代码。

7.4 await关键字

await是一个只能在协程函数中使用的关键字,用于遇到IO操作时挂起 当前协程(任务),当前协程(任务)挂起过程中 事件循环可以去执行其他的协程(任务),当前协程IO处理完成时,可以再次切换回来执行await之后的代码,

await + 可等待对象(协程对象、Future对象、Task对象)

示例1:await+协程对象

import asyncio  async def func1():  print("start")  await asyncio.sleep(1)  print("end")  return "func1执行完毕"  async def func2():  print("func2开始执行")  # await关键字后面可以跟可等待对象(协程对象、Future对象、Task对象)  response = await func1()  print(response)  print("func2执行完毕")  asyncio.run(func2())

示例2: 协程函数中可以使用多次await关键字

import asyncio  async def func1():  print("start")  await asyncio.sleep(1)  print("end")  return "func1执行完毕"  async def func2():  print("func2开始执行")  # await关键字后面可以跟可等待对象(协程对象、Future对象、Task对象)  response = await func1()  print(response)  response2 = await func1()  print(response2)  print("func2执行完毕")  asyncio.run(func2())

7.5 task对象

Tasks用于并发调度协程,通过asyncio.create_task(协程对象)的方式创建Task对象,这样可以让协程加入事件循环中等待被调度执行。除了使用 asyncio.create_task() 函数以外,还可以用低层级的 loop.create_task() 或 ensure_future() 函数。不建议手动实例化 Task 对象。

本质上是将协程对象封装成task对象,并将协程立即加入事件循环,同时追踪协程的状态。

注意:asyncio.create_task() 函数在 Python 3.7 中被加入。在 Python 3.7 之前,可以改用低层级的 asyncio.ensure_future() 函数。

示例1:

import asyncio  async def func():  print(1)  await asyncio.sleep(1)  print(2)  return "func的返回值"  async def main():  print(3)  # 创建协程,将协程封装到一个task对象中并立即添加到事件循环列表中,等待事件循环去执行,(默认是就绪状态)  task1 = asyncio.create_task(func())  # 创建协程,将协程封装到一个task对象中并立即添加到事件循环列表中,等待事件循环去执行,(默认是就绪状态)  task2 = asyncio.create_task(func())  # 当执行某协程遇到IO操作时,会自动化切换执行其他任务。  # 此处的await是等待相对应的协程全都执行完毕并获取结果  ret1 = await task1  ret2 = await task2  print(ret1, ret2)  asyncio.run(main())

示例2:用的还是比较多的

import asyncio  async def func():  print(1)  await asyncio.sleep(1)  print(2)  return "func的返回值"  async def main():  print(3)  # 创建协程,将协程封装到Task对象中并添加到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。  # 在调用  task_list = [    asyncio.create_task(func()),    asyncio.create_task(func())  ]  # 当执行某协程遇到IO操作时,会自动化切换执行其他任务。  # 此处的await是等待所有协程执行完毕,并将所有协程的返回值保存到done  # 如果设置了timeout值,则意味着此处最多等待的秒,完成的协程返回值写入到done中,未完成则写到pending中。  done, pending = await asyncio.wait(task_list, timeout=None)  print(done)  print(pending)  asyncio.run(main())

 示例3:

import asyncio  async def func():  print("执行协程函数内部代码")  # 遇到IO操作挂起当前协程(任务),等IO操作完成之后再继续往下执行。当前协程挂起时,事件循环可以去执行其他协程(任务)。  response = await asyncio.sleep(2)  print("IO请求结束,结果为:", response)  coroutine_list = [func(), func()]# 错误:coroutine_list = [ asyncio.create_task(func()), asyncio.create_task(func()) ]# 此处不能直接 asyncio.create_task,因为将Task立即加入到事件循环的任务列表,# 但此时事件循环还未创建,所以会报错。# 使用asyncio.wait将列表封装为一个协程,并调用asyncio.run实现执行两个协程# asyncio.wait内部会对列表中的每个协程执行ensure_future,封装为Task对象。done, pending = asyncio.run(asyncio.wait(coroutine_list))

总结:

在程序中只要看到asyncawait关键字,其内部就是基于协程实现的异步编程,这种异步编程是通过一个线程在IO等待时间去执行其他任务,从而实现并发。

如果是 I/O 密集型,且 I/O 请求比较耗时的话,使用协程。
如果是 I/O 密集型,且 I/O 请求比较快的话,使用多线程。
如果是 计算 密集型,考虑可以使用多核 CPU,使用多进程。

关于“python中asyncio异步编程的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

python中asyncio异步编程的示例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

python中asyncio异步编程的示例分析

这篇文章将为大家详细讲解有关python中asyncio异步编程的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1. 想学asyncio,得先了解协程携程的意义:计算型的操作,利用协程来回切换
2023-06-14

JavaScript中异步编程的示例分析

这篇文章给大家分享的是有关JavaScript中异步编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。目的提升开发效率,编写易维护的代码引子问题请求时候为什么页面卡死??$.ajax({ url: "
2023-06-15

c#中异步编程的示例分析

这篇文章给大家分享的是有关c#中异步编程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、什么算异步?  广义来讲,两个工作流能同时进行就算异步,例如,CPU与外设之间的工作流就是异步的。在面向服务的系
2023-06-14

C#异步编程的示例分析

小编给大家分享一下C#异步编程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!异步编程在处理并发方面被使用的越来越多,之所以说上面一句话,是为了区分多线程
2023-06-17

Python asyncio的示例分析

Python asyncio的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。我们先从一个常见的Python编程错误开始说起,我已经见过非常多的程序员犯过这种错误了:
2023-06-22

Python 中怎么使用Asyncio实现异步编程

Python 中怎么使用Asyncio实现异步编程,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。异步是怎么一回事?在传统的顺序编程中, 所有发送给解释器的指令会一条条被执行
2023-06-17

Python中怎么利用Asyncio实现异步编程

本篇文章为大家展示了Python中怎么利用Asyncio实现异步编程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。异步是怎么一回事?在传统的顺序编程中, 所有发送给解释器的指令会一条条被执行。此类代
2023-06-17

C#中异步多线程的示例分析

这篇文章主要介绍C#中异步多线程的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!进程、线程1. 进程首先了解,什么是线程? 即一个应用程序运行时,占用资源的综合是一个进程。Windows 任务管理器里面可以看
2023-06-25

JS中异步和单线程的示例分析

这篇文章主要介绍了JS中异步和单线程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。单线程但是我们在开发中,遇到请求网络,或者定时任务的时候,如果等待网络请求结束或者
2023-06-15

C#异步多线程中Thread的示例分析

这篇文章给大家分享的是有关C#异步多线程中Thread的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Thread API这里对 Thread 的一些常用 API 进行介绍,使用一些案例进行说明。由于 T
2023-06-25

python中的asyncio异步协程怎么实现

这篇“python中的asyncio异步协程怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“python中的async
2023-06-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录