协程

协程 (corountine):又称微线程。

asyncio,在单线程利用CPU和IO同时执行的原理,实现函数异步执行

实现协程就是要多个任务的循环,await是挂起命令。每到一个地方await一次,然后await返回。知道最终全部返回,程序结束。

关键对象

  1. 事件循环 - Eventloop :协程不能直接运行,需要把协程加到时间循环(loop).
  2. 协程对象,协程方法. async/await 原生协程 协程方法实现
  3. Future & Task 对象。 task – loop机制 (多个任务循环)
  4. 注册事件循环. 将协程注册到事件循环并启动。loop.run_until_completed会阻塞程序直到所有的协程对象都执行完毕。
  5. 启动结果获取。 task.result()

1. 事件循环

协程代码之间不断切换,形成的闭环范围作为一个事件循环.

#获取事件循环
loop = asyncio.get_event_loop()

2. 协程对象

协程对象,指一个使用async关键字定义的函数。它的调用不会立即执行函数,需要注册到事件循环,由事件循环调用。

本质:被 async 关键定义的协程,实际上是一个Coroutine对象,而Coroutine又继承Awaitable
from collections.abc import Coroutine, Awaitable

# 定义协程函数
async def work(self):while self.que.qsize() > 0:try:url = self.que.get(timeout=1)await asyncio.sleep(1)print(f"{os.getpid()}正在请求url:{url}")return os.getpid()except Exception as e:import  tracebackprint("---------------err", traceback.format_exc())break

3. Future & Task 对象

具体执行的任务

创建Task的方法
# 方法1:使用ensure_future方法。future代表一个对象,未执行的任务。
task1 = asyncio.ensure_future(func1(1))
task2 = asyncio.ensure_future(func1(2))# 方法3:使用Python 3.7提供的asyncio.create_task方法
task1 = asyncio.create_task(func1(1))
task2 = asyncio.create_task(func1(2))

创建Future对象的时候,状态为pending,事件循环调用执行的时候就是running,调用完毕就是done,如果需要取消Future对象的调度执行,可调用Future对象的cancel()函数。

Future对象方法
result():立即返回Future对象运行结果或者抛出执行时的异常,没有timeout参数,如果Future没有完成,不会阻塞等待结果,而是直接抛出InvalidStateError异常。最好的方式是通过await获取运行结果,await会自动等待Future完成返回结果,也不会阻塞事件循环,因为在asyncio中,await被用来将控制权返回给事件循环。done():非阻塞的返回Future对象是否成功取消或者运行结束或被设置异常,而不是查看future是否已经执行完成。
cancelled():判断Future对象是否被取消。
add_done_callback():传入一个可回调对象,当Future对象done时被调用。
exception():获取Future对象中的异常信息,只有当Future对象done时才会返回。
get_loop():获取当前Future对象绑定的事件循环。

4. 注册事件循环

创建demo1
#获取时间循环
loop = asyncio.get_event_loop()
#创建任务任务asyncio.ensure_future
task = [asyncio.ensure_future(work1(i)) for i in range(5)]
# 将任务注册到时间循环里
loop.run_until_complete(asyncio.wait(task))
loop.close()
创建demo2

这里使用asyncio.gather收集任务列表,无需创建函数

import asyncioasync def func1(i):print(f"协程函数{i} 马上执行")await asyncio.sleep(2)  print(f"协程函数{i} 执行完毕!")async def main():tasks = []for i in  range(1, 5):#这里未由协程函数创建协程任务tasks.append(func1(i))# gather自动将函数列表封装成了协程任务await  asyncio.gather(*tasks)if __name__ == '__main__':asyncio.run(main())

注意点: 协程的实现函数必须要通过await asyncio.sleep(time)来实现。 time.sleep是没效果的

5. 启动方式

  • loop.run_until_complete(asyncio.gather(*tasks)) #gather自动将函数列表封装成了协程任务,返回结果顺序
  • loop.run_until_complete(asyncio.wait(task))

6. 返回结果处理

asyncio.wait 会返回两个值:done 和 pending,done 为已完成的协程任务列表,pending 为超时未完成的协程任务类别,需通过task.result()方法可以获取每个协程任务返回的结果;

asyncio.gather 返回的是所有已完成协程任务的 result,不需要再进行调用或其他操作,就可以得到全部结果。

demo1
import asyncio
async def func1(i):print(f"协程函数{i}马上执行。")await asyncio.sleep(2)return i
async def main():tasks = []for i in range(1, 5):tasks.append(asyncio.create_task(func1(i)))# 获取任务结果done, pending = await asyncio.wait(tasks)for task in done:print(f"执行结果: {task.result()}")if __name__ == '__main__':asyncio.run(main())

demo2: 使用loop_run 执行,task.result 返回参数

def run(self):task = []# 开启多协程loop = asyncio.get_event_loop()for i in range(1000):# 调用工作函数task.append(asyncio.ensure_future(self.work()))loop.run_until_complete(asyncio.wait(task))#loop.run_until_complete(asynciogather(*tasks))  #这种有序返回也可以res = [t.result() for t in task ]loop.close()print(res)
demo3: asynico.gather 按执行顺序返回结果
# gather自动将函数列表封装成了协程任务
results = await asyncio.gather(*tasks)
for res in results:
print("-------------res",res)
  • gather具有把普通协程函数包装成协程任务的能力,wait没有。wait只能接收包装后的协程任务列表做参数。
  • 两者返回值不一样,wait返回的是已完成和未完成任务的列表,而gather直接返回协程任务执行结果。
  • gather返回的任务执行结果是有序的,wait方法获取的结果是无序的。

多线程 + 多协程

import asyncio
import os
import time
from multiprocessing import Process, Queuedef time_count(func):def wrapper(*args, **kwargs):start_time = time.time()func(*args, **kwargs)end_time = time.time()print("总耗时:", end_time - start_time)return wrapperclass Myprocess(Process):def __init__(self, que):super().__init__()self.que = que# 重写run方法def run(self):task = []# 开启时间循环loop = asyncio.get_event_loop()for i in range(1000):# 调用工作函数task.append(asyncio.ensure_future(self.work()))loop.run_until_complete(asyncio.wait(task))# loop.run_until_complete(asyncio.gather(*task))  两种方法都可以res = [t.result() for t in task]loop.close()print(res)# 定义工作函数async def work(self):while self.que.qsize() > 0:try:url = self.que.get(timeout=1)await asyncio.sleep(1)print(f"{os.getpid()}正在请求url:{url}")return os.getpid()except Exception as e:break@time_count
def main():q = Queue()for i in range(10000):q.put(f"https://www.baidu.com--{i}")process_list = []for i in range(4):p = Myprocess(q)process_list.append(p)p.start()for p in process_list:p.join()print("任务结束")if __name__ == '__main__':main()# 使用asyncio改写, 加入函数返回值
# 总耗时: 5.137028455734253

参考

  • https://www.jianshu.com/p/75b445a55536
  • https://blog.csdn.net/qq_37674086/article/details/113879117
  • https://zhuanlan.zhihu.com/p/169426477 #通俗易懂

python协程asyncio使用相关推荐

  1. Python 协程 asyncio 极简入门与爬虫实战

    在了解了 Python 并发编程的多线程和多进程之后,我们来了解一下基于 asyncio 的异步IO编程--协程 01 协程简介 协程(Coroutine)又称微线程.纤程,协程不是进程或线程,其执行 ...

  2. python协程asyncio 应用_Python-如何使用asyncio同时运行多个协程?

    TL:DR使用^{}同时运行多个协程.Maybe this scenario requires a framework based on events/callbacks rather than on ...

  3. python协程—asyncio模块

    为什么使用协程? 当多线程或者多进程足够多时,实际上并不能解决性能的瓶颈问题,也就是多线程和多进程对小规模的请求可以提高效率,过多的请求实际上会降低服务资源响应效率,因此协程是更好的解决文案. 什么是 ...

  4. python 协程 php,python3.x,协程_python协程练习部分代码的理解?,python3.x,协程,asyncio - phpStudy...

    python协程练习部分代码的理解? import asyncio import threading async def wget(host): print('wget {}'.format(host ...

  5. python 协程 asyncio_Python 原生协程------asyncio(选自公众号)

    所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyncio 是并发(concurrency)的一种方式.对 Python 来说,并 ...

  6. python 协程_Python 协程与 Go 协程的区别(一)

    ? "Python猫" ,一个值得加星标的公众号 花下猫语:年关将近,不知各位过得怎样?我最近有些忙,收获也挺多,以后有机会分享下.吃饭时间,追了两部剧<了不起的麦瑟尔夫人& ...

  7. python协程实时输出_python协程

    不知道你有没有被问到过有没有使用过的python协程? 协程是什么? 协程是一种用户态轻量级,是实现并发编程的一种方式.说到并发,就能想到了多线程 / 多进程模型,是解决并发问题的经典模型之一. 但是 ...

  8. python中协程与函数的区别_深入浅析python 协程与go协程的区别

    进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...

  9. python 协程可以嵌套协程吗_Python线程、协程探究(2)——揭开协程的神秘面纱...

    一.上集回顾 在上一篇中我们主要研究了python的多线程困境,发现多核情况下由于GIL的存在,python的多线程程序无法发挥多线程该有的并行威力.在文章的结尾,我们提出如下需求: 既然python ...

最新文章

  1. 实现微服务架构-微服务架构需要解决的问题
  2. 弹出硬盘时应用程序阻碍停用设备_7GB硬盘空间被Win 10“偷走”?微软系统的这些“潜规则”你掌握了吗?...
  3. 吴麒pdf 自动控制原理下_设施大棚灌溉设备工作原理
  4. UML建模的要点总结
  5. 时下最流行前端构建工具Webpack 入门总结
  6. 前端开发有哪些技术栈要掌握_为什么要掌握前端开发的这四个主要概念
  7. 三次握手的第三个ACK包丢了,会发生什么?
  8. java中0x07_JAVA里0X00的表示
  9. python网络编程学习笔记(4):域名系统
  10. 计算机模拟与生态工程,2018年环境生态工程专业分析及就业前景
  11. 机器学习-Adaboost 算法(集成学习)
  12. 一个新基民的感叹:人心不足蛇吞象
  13. 基于 React.js + redux + bootstrap 的 RubyChina 示例
  14. 超硬核!数据结构学霸笔记,考试面试吹牛就靠它
  15. SQL Server数据库学习(1)
  16. 探索Holo_java操作日期
  17. SpringAOP:连接点和切点的区别
  18. 从祖师级到新生代,48位开发者的“武功秘籍”
  19. 8 Flask mega-tutorial 第8章 关注 Followers
  20. 《拆掉思维里的墙》读书笔记

热门文章

  1. manifold安装记录
  2. 五原县扬帆志愿者协会开展“春节慰问送温暖,年味渐浓情更深”新春慰问活动
  3. 2023年计算机专业的毕业设计题目大全-喜欢可以收藏
  4. mysql galera 下载_MySQL galera 的安装使用
  5. Java技能树-RE-正则应用-findstr篇
  6. FPGA开发中全局复位置位(GSR)简介
  7. 用计算机唱下山歌词,太阳落下山秋虫儿闹声喧是什么歌_太阳落下山秋虫儿闹声喧歌名、歌词、歌手介绍_游戏吧...
  8. 手机支付流程之华为补单
  9. 云原生主题学习月|共同学习全球领先的亚马逊云科技云原生课程,组团共学拿奖励~
  10. 一款App等保的预检测工具--ApplicationScanner