Python中篇 3. asyncio中协称如何被事件循环调度的-Future/Task是关键先生

简介: Python中篇 3. asyncio中协称如何被事件循环调度的-Future/Task是关键先生

1. 前言



大家比较好奇,我们讲了那么多的协称和事件循环知识,为啥一直没有提到事件循环如何调度协称的呢?不好意思哈,我想把大家的好奇心留在这一篇文章中,接下来我希望你们拿好板凳,带上瓜子和水,用眼睛往下瞅。


我们接下来了解两个概念,在说说协称如何被调度


2. Future对象



asyncio中,如何才能得到异步调用的结果呢?先设计一个对象,异步调用执行完的时候,就把结果放在它里面,这种对象称之为未来对象。未来对象有一个result方法,可以获取未来对象的内部结果。还有个set_result方法,是用于设置result的。set_result设置的是什么,调用result得到的就是什么。Future对象可以看作下面的Task对象的容器。


3. Task对象



一个协程就是一个原生可以挂起的函数,Task则是对象协程的进一步封装,里面可以包含协程在执行时的各种状态,关于TaskFuture两者之前的关系我们后面会说。


4. Task和Future与协程的关系



TaskFuture的派生类,它有一个核心step方法,这个方法和协称调度有关,但是这个方法只有Task独有,Future是没有的,但是Futureset_result方法,这个方法可以被FutureTask共同调用。同时TaskFuture和协称之间的桥梁,因为Task执行结束的时候会调用Futureset_result方法,这样Future通过result方法就会知道协称运行的结果,所以说Future想要知道协称的运行结果,那么必须将协称绑定Task,这样Task才能把结果设置到Future中。


5. 协称如何被事件循环调度



对于协程来说,是没有办法直接放到事件循环里面运行的,需要Task对象(任务)。而我们之前直接将协程扔进loop中是因为asyncio内部会有检测机制,如果是协程的话,会自动将协程包装成一个Task对象。例如:


import asyncio
async def coroutine():
    print("hello world")
if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    # 如何创建一个任务呢?
    task = loop.create_task(coroutine())
    loop.run_until_complete(task)
运行结果:
"""
hello world
"""


事件循环怎么调度协称的呢?


loop通过create_task(coroutine())创建task,入参是协称,task在初始化的时候会调用:loop.call_soon(self._step),然后call_soon会在loop的_ready回调队列中添加一个Handle实例,最后为task对象添加一个done callback来停止loop。

task初始化完成,我们运行loop.run_until_complete(task)最终会调用loop.run_forever()

loop.run_forever()本质是一个while循环,只要loop没有被标记为停止,就会反复调用self._run_once(),在_run_once()中,loop会将_ready回调队列中所有的Handle实例依次取出并执行,这里就执行到了前面task实例的_step()

_step方法会执行两个重要操作,第一个就是启动协称的运行,通过调用协称的send(None)方法启动。第二个就是协称运行完毕会抛出StopIteration异常,而这个异常里面的value就是协称返回的值,把这个value通过Futureset_result方法设置进去,这样我们的Task或者Future就会通过Result获取返回值,即协称的返回值。我们通常在代码中等待协称返回都是如下这种方式:

result = await future //相当于调用Future.Result()方法
result = await task //同上

这样我们就可以拿到协称的返回值,而事件循环会继续在_ready队列中查找有没有其他的待运行Handler实例。


参考:https://segmentfault.com/q/1010000016451903


6. 小结



总结一下核心重点:TaskFuture和协称之间的桥梁,而协称的调度离不开事件循环,事件循环又通过Task生成Handler实例,最终被事件循环调度,所以说asyncio复杂背后的设计逻辑是环环相扣的,只有把相关概念和原理吃透,你才能彻底掌握他们。

相关文章
|
1天前
|
调度 Python
python知识点100篇系列(20)-python协程与异步编程asyncio
【10月更文挑战第8天】协程(Coroutine)是一种用户态内的上下文切换技术,通过单线程实现代码块间的切换执行。Python中实现协程的方法包括yield、asyncio模块及async/await关键字。其中,async/await结合asyncio模块可更便捷地编写和管理协程,支持异步IO操作,提高程序并发性能。协程函数、协程对象、Task对象等是其核心概念。
|
5天前
|
调度 开发者 Python
异步编程在Python中的应用:Asyncio和Coroutines
【10月更文挑战第12天】本文介绍了Python中的异步编程,重点讲解了`asyncio`模块和协程的概念、原理及使用方法。通过异步编程,程序可以在等待I/O操作时继续执行其他任务,提高整体效率。文章还提供了一个简单的HTTP服务器示例,展示了如何使用`asyncio`和协程编写高效的异步代码。
12 2
|
7天前
|
调度 开发者 Python
异步编程在Python中的应用:Asyncio和Coroutines
【10月更文挑战第10天】本文介绍了Python中异步编程的应用,重点讲解了`asyncio`模块和协程的概念、原理及使用方法。通过一个简单的HTTP服务器示例,展示了如何利用`asyncio`和协程实现高效的并发处理。
14 1
|
11天前
|
调度 开发者 Python
探索Python中的异步编程:从asyncio到Trio
在这个快节奏的技术世界里,Python的异步编程正变得越来越重要。本文将带你深入Python的异步编程世界,从asyncio的基础用法,到Trio的高级特性,我们将一探究竟。准备好,让我们一起揭开Python异步编程的神秘面纱。
|
9天前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
31 0
|
11天前
|
监控 Python
探索Python中的异步编程:Asyncio模块的魔力
在这篇文章中,我们将深入探讨Python的Asyncio模块,这是Python异步编程的核心。我们将一起揭开异步编程的神秘面纱,学习如何使用async和await关键字来编写非阻塞代码,以及如何利用异步编程提高应用程序的性能。
|
9天前
|
存储 程序员 开发者
Python编程基础:从入门到实践
【10月更文挑战第8天】在本文中,我们将一起探索Python编程的奇妙世界。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的信息。我们将从Python的基本概念开始,然后逐步深入到更复杂的主题,如数据结构、函数和类。最后,我们将通过一些实际的代码示例来巩固我们的知识。让我们一起开始这段Python编程之旅吧!
|
3天前
|
设计模式 开发者 Python
Python编程中的设计模式:从入门到精通####
【10月更文挑战第14天】 本文旨在为Python开发者提供一个关于设计模式的全面指南,通过深入浅出的方式解析常见的设计模式,帮助读者在实际项目中灵活运用这些模式以提升代码质量和可维护性。文章首先概述了设计模式的基本概念和重要性,接着逐一介绍了几种常用的设计模式,并通过具体的Python代码示例展示了它们的实际应用。无论您是Python初学者还是经验丰富的开发者,都能从本文中获得有价值的见解和实用的技巧。 ####
|
10天前
|
机器学习/深度学习 数据采集 数据挖掘
探索Python编程的奥秘
【10月更文挑战第7天】本文将带你走进Python的世界,探索其背后的逻辑与魅力。我们将从基础语法开始,逐步深入到函数、面向对象编程等高级特性,最后通过实际项目案例,让你体验Python的强大与便捷。无论你是编程新手,还是有一定基础的开发者,都能在这篇文章中找到你需要的信息和启发。
|
11天前
|
IDE 开发工具 Python
Python 编程入门:打造你的第一个程序
【10月更文挑战第6天】编程,这个听起来高大上又充满神秘感的领域,其实就像学习骑自行车一样。一开始你可能会觉得难以掌握平衡,但一旦你学会了,就能自由地穿梭在广阔的道路上。本文将带你走进 Python 的世界,用最简单的方式让你体验编写代码的乐趣。不需要复杂的理论,我们将通过一个简单的例子——制作一个猜数字游戏,来实践学习。准备好了吗?让我们开始吧!