协程学习笔记

本文详细介绍了Python协程的概念、应用场景,以及如何使用async/await进行并发编程。通过实例展示了如何利用asyncio库创建和管理协程,强调了协程在I/O密集型任务中的高效性,并通过对比分析展示了异步请求如何提升并发性能。最后,通过增加任务数量验证了协程在处理大量网络请求时的优势。
摘要由CSDN通过智能技术生成

协程

协程是轻量级线程,拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此协程能保留上一次调用时的状态,即所有局部状态的一个特定组合,每次过程重入时,就相当于进入上一次调用的状态。

协程的应用场景:I/O 密集型任务。这一点与多线程有些类似,但协程调用是在一个线程内进行的,是单线程,切换的开销小,因此效率上略高于多线程。当程序在执行 I/O 时操作时,CPU 是空闲的,此时可以充分利用 CPU 的时间片来处理其他任务。在单线程中,一个函数调用,一般是从函数的第一行代码开始执行,结束于 return 语句、异常或者函数执行(也可以认为是隐式地返回了 None )。 有了协程,我们在函数的执行过程中,如果遇到了耗时的 I/O 操作,函数可以临时让出控制权,让 CPU 执行其他函数,等 I/O 操作执行完毕以后再收回控制权。

定义协程

Python3.4 加入了协程的概念,以生成器对象为基础,在 Python3.5 则增加了关键字 async/await,使得协程的实现更加方便。Python 中使用协程最常用的库莫过于 asyncio ,接下来我们以 asyncio 为基础来介绍协程的使用。
先看一个简单的例子来理解

1  import asyncio
2  import time
3  
4  
5  async def task():
6      print(f"{time.strftime('%H:%M:%S')} task 开始 ")
7      time.sleep(2)
8      print(f"{time.strftime('%H:%M:%S')} task 结束")
9  
10  
11  coroutine = task()
12  print(f"{time.strftime('%H:%M:%S')} 产生协程对象 {coroutine},函数并未被调用")
13  loop = asyncio.get_event_loop()
14  print(f"{time.strftime('%H:%M:%S')} 开始调用协程任务")
15  start = time.time()
16  loop.run_until_complete(coroutine)
17  end = time.time()
18  print(f"{time.strftime('%H:%M:%S')} 结束调用协程任务, 耗时{end - start} 秒")
19

运行结果如下所示

22:34:06 产生协程对象 <coroutine object task at 0x0000025B8CE62200>,函数并未被调用
22:34:06 开始调用协程任务
22:34:06 task 开始 
22:34:08 task 结束
22:34:08 结束调用协程任务, 耗时2.015564203262329

说明:首先引入 asyncio ,这样才可以使用 async 和 await 关键字( async 定义一个协程, await 用来临时挂起一个函数或方法的执行),接着我们使用 async 定义一协程方法,
随后我们直接调用了这个方法,然而这个方法并没有执行,而是返回了一个 coroutine 协程对象。随后我们使用 get_event_loop() 方法创建一个事件循环 loop ,并调用了 loop 对象的 run_until_complete() 方法将协程注册到事件循环 loop 中,然后启动。最后我们才看到了 task 方法打印了输出结果。
注意: async 定义的方法无法直接执行,必须将其注册到事件循环中才可以执行。

我们还可以为任务绑定回调函数:

1  import asyncio
2  import time
3  
4  
5  async def _task():
6      print(f"{time.strftime('%H:%M:%S')} task 开始 ")
7      time.sleep(2)
8      print(f"{time.strftime('%H:%M:%S')} task 结束")
9      return "运行结束"
10  
11  
12  def callback(task):
13      print(f"{time.strftime('%H:%M:%S')} 回调函数开始运行")
14      print(f"状态:{task.result()}")
15  
16  
17  coroutine = _task()
18  print(f"{time.strftime('%H:%M:%S')} 产生协程对象 {coroutine},函数并未被调用"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值