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复杂背后的设计逻辑是环环相扣的,只有把相关概念和原理吃透,你才能彻底掌握他们。

相关文章
|
13天前
|
Python
Python中的异步编程:使用asyncio和aiohttp实现高效网络请求
【10月更文挑战第34天】在Python的世界里,异步编程是提高效率的利器。本文将带你了解如何使用asyncio和aiohttp库来编写高效的网络请求代码。我们将通过一个简单的示例来展示如何利用这些工具来并发地处理多个网络请求,从而提高程序的整体性能。准备好让你的Python代码飞起来吧!
35 2
|
17天前
|
调度 开发者 Python
Python中的异步编程:理解asyncio库
在Python的世界里,异步编程是一种高效处理I/O密集型任务的方法。本文将深入探讨Python的asyncio库,它是实现异步编程的核心。我们将从asyncio的基本概念出发,逐步解析事件循环、协程、任务和期货的概念,并通过实例展示如何使用asyncio来编写异步代码。不同于传统的同步编程,异步编程能够让程序在等待I/O操作完成时释放资源去处理其他任务,从而提高程序的整体效率和响应速度。
|
13天前
|
数据库 Python
异步编程不再难!Python asyncio库实战,让你的代码流畅如丝!
在编程中,随着应用复杂度的提升,对并发和异步处理的需求日益增长。Python的asyncio库通过async和await关键字,简化了异步编程,使其变得流畅高效。本文将通过实战示例,介绍异步编程的基本概念、如何使用asyncio编写异步代码以及处理多个异步任务的方法,帮助你掌握异步编程技巧,提高代码性能。
49 4
|
13天前
|
API 数据处理 Python
探秘Python并发新世界:asyncio库,让你的代码并发更优雅!
在Python编程中,随着网络应用和数据处理需求的增长,并发编程变得愈发重要。asyncio库作为Python 3.4及以上版本的标准库,以其简洁的API和强大的异步编程能力,成为提升性能和优化资源利用的关键工具。本文介绍了asyncio的基本概念、异步函数的定义与使用、并发控制和资源管理等核心功能,通过具体示例展示了如何高效地编写并发代码。
25 2
|
24天前
|
调度 开发者 Python
异步编程在Python中的应用:Asyncio和Coroutines
异步编程在Python中的应用:Asyncio和Coroutines
20 1
|
8天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
8天前
|
机器学习/深度学习 数据挖掘 Python
Python编程入门——从零开始构建你的第一个程序
【10月更文挑战第39天】本文将带你走进Python的世界,通过简单易懂的语言和实际的代码示例,让你快速掌握Python的基础语法。无论你是编程新手还是想学习新语言的老手,这篇文章都能为你提供有价值的信息。我们将从变量、数据类型、控制结构等基本概念入手,逐步过渡到函数、模块等高级特性,最后通过一个综合示例来巩固所学知识。让我们一起开启Python编程之旅吧!
|
8天前
|
存储 Python
Python编程入门:打造你的第一个程序
【10月更文挑战第39天】在数字时代的浪潮中,掌握编程技能如同掌握了一门新时代的语言。本文将引导你步入Python编程的奇妙世界,从零基础出发,一步步构建你的第一个程序。我们将探索编程的基本概念,通过简单示例理解变量、数据类型和控制结构,最终实现一个简单的猜数字游戏。这不仅是一段代码的旅程,更是逻辑思维和问题解决能力的锻炼之旅。准备好了吗?让我们开始吧!
|
2天前
|
存储 人工智能 数据挖掘
Python编程入门:打造你的第一个程序
本文旨在为初学者提供Python编程的初步指导,通过介绍Python语言的基础概念、开发环境的搭建以及一个简单的代码示例,帮助读者快速入门。文章将引导你理解编程思维,学会如何编写、运行和调试Python代码,从而开启编程之旅。
22 2
下一篇
无影云桌面