范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

在Python中使用Asyncio系统(34)Task和Future

  Task 和 Future
  前面我们讨论了协程,以及如何在循环中运行它们才有用。现在我想简单谈谈Task和Future api。你将使用最多的是Task,因为你的大部分工作将涉及使用create_task()函数运行协程,就像在第22页的"快速开始"中设置的那样。Future类实际上是Task的超类,它提供了与循环交互操作的所有功能。
  可以这样简单地理解:Future表示某个活动的未来完成状态,并由循环管理。Task是完全相同的,但是具体的"activity"是一个协程——可能是你用async def函数加上create_task()创建的协程。
  Future类表示与循环交互的某个东西的状态。这个描述太模糊了,不太有用,所以你可以将Future实例视为一个切换器,一个完成状态的切换器。当创建Future实例时,切换设置为"尚未完成"状态,但稍后它将是"完成"状态。事实上,Future实例有一个名为done()的方法,它允许你检查状态,如示例 3-15所示。
  示例 3-15. 用done()方法检查完成状态  >>> from asyncio import Future >>> f = Future() >>> f.done() False
  Future实例还可以执行以下操作:
  • 设置一个result值(用.set_result(value)设置值并且使用 .result()获取值)
  • 使用.cancel()方法取消 (并且会用使用.cancelled()检查是否取消)
  • 增加一个Future完成时回调的函数
  即使Task更常见,也不可能完全避免使用Future:例如,在执行器上运行函数将返回Future实例,而不是Task。让我们快速看一下 示例 3-16 ,了解一下直接使用Future实例是什么感觉。
  示例 3-16. 与Future实例的交互  >>> import  asyncio >>> >>> async def main(f: asyncio.Future):   ... await asyncio.sleep(1) ... f.set_result("I have finished.")   ... >>> loop = asyncio.get_event_loop() >>> fut = asyncio.Future()   >>> print(fut.done())   False >>> loop.create_task(main(fut))   :1>> >>> loop.run_until_complete(fut)    "I have finished." >>> print(fut.done()) True >>> print(fut.result()) I have finished.
  (L3)创建一个简单的 main函数。我们运行这个函数,等上一会儿然后在Future f上设置一个结果。
  (L5)设置一个结果。
  (L8)手动创建一个Future实例。注意,这个实例(默认情况下)绑定到我们的循环,但它没有也不会被附加到任何协程(这就是Tasks的作用)。
  (L9)在做任何事情之前,确认future还没有完成。
  (L11)安排main()协程,传递future。请记住,main()协程所做的所有工作就是sleep,然后切换Future实例。(注意main()协程还不会开始运行:协程只在事件循环运行时才开始运行。)
  (L13)在这里我们在Future实例上而不是Task实例上使用run_until_complete()。这和你以前见过的不一样。现在循环正在运行,main()协程将开始执行.
  (L16)最终,当future的结果被设置时,它就完成了。完成后,可以访问结果。
  当然,你不太可能以这里所示的方式直接使用Future;代码示例仅用于教育目的。你与asynccio的大部分联系都是通过Task实例进行的。
  你可能想知道如果在Task实例上调用set_result()会发生什么。在Python 3.8之前可以这样做,但现在不允许这么做了。任务实例是协程对象的包装器,它们的结果值只能在内部设置为底层协程函数的结果,如 示例 3-17所示那样。
  示例 3-17. 在task上调用set_result  >>> import  asyncio >>> from contextlib import suppress >>> >>> async def main(f: asyncio.Future): ... await asyncio.sleep(1) ... try: ... f.set_result("I have finished.")   ... except RuntimeError as e: ... print(f"No longer allowed: {e}") ... f.cancel()   ... >>> loop = asyncio.get_event_loop() >>> fut = asyncio.Task(asyncio.sleep(1_000_000))   >>> print(fut.done()) False >>> loop.create_task(main(fut)) :1>> >>> with suppress(asyncio.CancelledError): ... loop.run_until_complete(fut) ... No longer allowed: Task does not support set_result operation >>> print(fut.done()) True >>> print(fut.cancelled())   True
  (L13)唯一的区别是我们创建的是Task实例而不是Future实例。当然,Task API要求我们提供一个协程;这里我们使用sleep()只是因为简单方便。
  (L7)正在传入一个Task实例。它满足函数的类型签名(因为Task是Future的子类),但从Python 3.8开始,我们不再允许在Task上调用set_result():尝试这样做将引发RuntimeError。这个想法是,一个Task代表一个正在运行的协程,所以结果应该总是来自于task自身。
  (L10, L24)但是,我们仍然可以cancel()一个任务,它将在底层协程中引发CancelledError。
  Create_task? Ensure_Future? 下定决心吧!
  在第22页的"快速入门"中,我说过运行协程的方法是使用asyncio.create_task()。在引入该函数之前,有必要获取一个循环实例并使用loop.create_task()完成相同的任务。事实上,这也可以通过一个不同的模块级函数来实现:asyncio.ensure_future()。一些开发人员推荐create_task(),而其他人推荐ensure_future()。
  在我为这本书做研究的过程中,我确信API方法asyncio.ensure_future()是引起对asyncio库广泛误解的罪魁祸首。API的大部分内容都非常清晰,但在学习过程中还存在一些严重的障碍,这就是其中之一。当你遇到ensure_future()时,你的大脑会非常努力地将其集成到关于asyncio应该如何使用的心理模型中——但很可能会失败!
  在Python 3.6 asyncio 文档中,这个现在已经臭名昭著的解释突出了 ensure_future() 的问题:
  asyncio.ensure_future(coro_or_future, *,  _loop =None)
  安排执行一个协程对象:把它包装在future中。返回一个Task对象。如果参数是Future,则直接返回。
  什么!? 当我第一次读到这篇文章时,我很困惑。下面希望是对ensure_future()的更清楚的描述:  如果你传入一个协程,它将生成一个Task实例(你的协程将被调度在事件循环上运行)。这与调用asyncio.create_task()(或loop.create_task())并返回新的Task实例是相同的。  如果你传入一个Future实例(或者一个Task实例,因为Task是Future的子类),你会得到相同的东西返回,没有改变。是的,真的!
  这个函数很好地说明了针对终端用户开发人员的asyncio API(高级API)和针对框架设计人员的asyncio API(低级API)之间的区别。让我们在示例 3-18中自习看看它是如何工作的。
  示例 3-18. 仔细看看ensure_future()在做什么  import asyncio  async def f():       pass  coro = f()   loop = asyncio.get_event_loop()  task = loop.create_task(coro)   assert isinstance(task, asyncio.Task)  new_task = asyncio.ensure_future(coro)   assert isinstance(new_task, asyncio.Task)  mystery_meat = asyncio.ensure_future(task)   assert mystery_meat is task
  (L3)一个简单的什么都不做的协程函数。我们只需要一些能组成协程的东西。
  (L6)我们通过直接调用该函数来创建协程对象。你的代码很少会这样做,但我想在这里明确地表示,我们正在向每个create_task()和ensure_future()传递一个协程对象。
  (L7)获取一个循环。
  (L9)首先,我们使用loop.create_task()在循环中调度协程,并返回一个新的Task实例。
  (L10)验证类型。到目前为止,没有什么有趣的。
  (L12)我们展示了asyncio.ensure_future()可以被用来执行与create_task()相同的动作:我们传入了一个协程,并返回了一个Task实例(并且协程已经被安排在循环中运行)!如果传入的是协程,那么loop.create_task()和asyncio.ensure_future()之间没有区别。
  (L15)如果我们给ensure_future()传递一个Task实例会发生什么呢?注意我们要传递的Task实例是已经在第4步通过loop.create_task()创建好的。
  (L16)返回的Task实例与传入的Task实例完全相同:它在被传递时没有被改变。
  直接传递Future实例的意义何在?为什么用同一个函数做两件不同的事情?答案是,ensure_future()的目的是让框架作者向最终用户开发者提供可以处理两种参数的API。不相信我?这是ex-BDFL自己说的:
  ensure_future()的要点是,如果你有一个可能是协程或Future(后者包括一个Task,因为它是Future的子类)的东西,并且你想能够调用一个只在Future上定义的方法(可能唯一有用的例子是cancel())。当它已经是Future(或Task)时,它什么也不做;当它是协程时,它将它包装在Task中。
  如果您知道您有一个协程,并且希望它被调度,那么正确的API是create_task()。唯一应该调用ensure_future()的时候是当你提供一个API(像大多数asyncio自己的API),它接受协程或Future,你需要对它做一些事情,需要你有一个Future。
  —Guido van Rossum
  总而言之,asyncio.sure_future()是一个为框架设计者准备的辅助函数。这一点最容易通过与一种更常见的函数进行类比来解释,所以我们来做这个解释。如果你有几年的编程经验,你可能已经见过类似于例3-19中的istify()函数的函数。示例 3-19中listify()的函数。
  示例 3-19. 一个强制输入列表的工具函数  def listify(x: Any) -> List:     """ Try hard to convert x into a list """     if isinstance(x, (str, bytes)):         return [x]     try:         return [_ for _ in x]     except TypeError:         return [x]
  这个函数试图将参数转换为一个列表,不管输入的是什么。api和框架中经常使用这类函数将输入强制转换为已知类型,这将简化后续代码——在本例中,您知道参数(来自listify()的输出)将始终是一个列表。
  如果我将listify()函数重命名为ensure_list(),那么您应该开始看到与asyncio.ensure_future()的类似之处:它总是试图将参数强制转换为Future(或子类)类型。这是一个实用函数,它使框架开发人员(而不是像你我这样的终端用户开发人员)的工作变得更容易。
  实际上,asyncio标准库模块本身使用ensure_future()正是出于这个原因。当你下次查看API时,你会发现函数参数被描述为"可等待对象",很可能内部使用ensure_future()强制转换参数。例如,asyncio.gather()函数就像下面的代码一样:  asyncio.gather(*aws, loop=None, ...)
  aws参数表示"可等待对象",包括协程、task和future。在内部,gather()使用ensure_future()进行类型强制转换:task和future保持不变,而把协程强制转为task。
  这里的关键是,作为终端用户应用程序开发人员,应该永远不需要使用asyncio.ensure_future()。它更像是框架设计师的工具。如果你需要在事件循环上调度协程,只需直接使用asyncio.create_task()来完成。
  在接下来的几节中,我们将回到语言级别的特性,从异步上下文管理器开始。

带你深入了解OPPOReno6Pro名侦柯南定制版在7月28日,OPPO名侦探柯南限定系列产品正式发布,这次限定产品的类型包括了手机OPPOWatch2OPPO手环OPPOEncoFree2OPPOVOOC闪充移动电源。我手上这一OPPOWatch2到底值得入手吗?全面评测告诉你7月27日,在超能代表发布会上,OPPO正式发布了新一代全智能手表旗舰OPPOWatch2,我们拿到手的是46mm铂黑配色版,在经过了一个月使用之后,都给我们留下了十分深刻的印象,全新发布的OPPOFindX2Pro发布6999元值得购买吗?在3月6号OPPO发布了最新一代的旗舰手机,Findx系列,这一次分为两个版本一个是OPPOFindX2Pro,一个是OPPOFindX2Pro,我手上拿的这台是pro的版本。OP我国将制定氢能发展战略,氢燃料汽车有望弯道超车都知道未来是新能源汽车的天下,大众本田丰田现代等全球知名车企都开始往电气化转型,而奔驰奥迪等豪华品牌也加入到新能源汽车的大家庭,而宝马更是研发起氢燃料电池汽车,可见传统燃油车时代已OPPOReno5Pro游戏表现到底如何!带你去了解在2020年末的时候,OPPO发布了新的Reno系列,OPPOReno5,这一次一样有三个版本,分别是OPPOReno5和OPPOReno5Pro,还有一款是超大一杯的OPPORe传印度考虑降低进口电动车关税,特斯拉在印度建厂有戏了都知道未来是新能源汽车的天下,大众本田丰田现代等全球知名车企都开始往电气化转型,而豪华品牌也是如此,可见传统燃油车时代已经开始慢慢终结,而作为开挂民族的印度也开始重视新能源汽车市场2022款揽胜PHEV路试谍照曝光,奔驰G级迎来强敌今日我们从神奇的海外媒体获悉到2022款路虎揽胜PHEV的路试谍照,新车将在年内正式发布,其实先前运动版长轴版标准版已经全部曝光,这一次终于轮到揽胜PHEV了。外观方面依然延续了家2022款奔驰A级丐版车型谍照曝光,这个造型略显寒酸近日我们从神奇的海外媒体获悉了2022款奔驰A极大路试谍照,只不过这一次是一台两厢版本,话不多说,一起来看看吧!新车这一次只采用了轻微涂装,所以我们能通过细节得到不少有用的信息。大全新奇骏采用三缸机瞬间脱粉,同价位车型不妨看看它们说起SUV,不得不提提哈弗H6本田CRV跟丰田RAV4,这三款车可以说是消费者最喜欢的车型,深受消费者的喜爱。而日产奇骏虽然不如它们销量火爆,但是也有着自己庞大的粉丝群体,不过全新走出去,引进来,雷诺吉利联手,新能源汽车迎来高光时刻不知道什么时候开始,汽车行业也开始流行合作,这不近日吉利官方宣布将于雷诺集团建立创新性合作伙伴关系,双方将在中国韩国展开亲密合作。主要合作事宜为联合开发全新混动车型。这一次合作可以2021年北美电影票房第26周,速度与激情9梅开二度文Leon本文为原创,转载请注明出处。本周北美电影市场依然是高潮依旧,共有三部新片上映,其中环球公司自己就占了两部,宝贝老板2和人类清除计划5分别占据了第二和第三的位置,而第一依然
彻底封杀抖音TikTok?美国考虑将字节跳动列入实体清单彻底封杀抖音TikTok?美国考虑将字节跳动列入实体清单美国现在已经开始对中国科技企业进行全面的围堵,封杀了华为等一干实体科技企业还不够,他们还准备对中国的软件企业下手。近段时间,名企头条冒充老干妈员工行骗嫌疑人被批捕字节跳动回应交易禁令余承东消费者业务上半年收入2558亿元手机发货量1。05亿台华为消费者业务CEO余承东透露,华为消费者业务上半年销售收入2558亿元,上半年华为手机全球发货量1。05亿台。今年第二LK分享中国启动全球最大规模碳市场广受关注的全国碳排放权交易于7月16日正式开市。在日前举办的国务院新闻办政策例行吹风会上,生态环境部副部长赵英民透露,中国碳市场将成为全球覆盖温室气体排放量规模最大的市场。赵英民表高精度地图在车路协同中的应用在目前的自动驾驶技术演化路线中,单车智能和车路协同是主要的两大发展方向,基于中国国情,新基建与5G技术发展势头迅猛,车路协同极有可能成为实现交通强国的手段之一。除了要有聪明的车,也小户型最佳选择,雷鸟4K高清画质电视I49UI体验报告前不久,TCL集团旗下高端互联网电视品牌雷鸟正式发布,随着品牌一起面市的还有主打4K高清画质的I55UI电视,一经上市便取得了非常优秀的市场表现,用户馈也首屈一指,在京东平台上的好小身材大能量爱奇艺电视果一年使用测评电视有些不一样,家庭换新迭代都不及手机来的频繁,但智能浪潮毫无意外的席卷了电视市场,技术日新月异,各种专业名词琳琅满目,搞得消费者晕头转向,除了面板技术之外,更多的则体现在智能一词如何评价小米发布的Civi手机,有哪些亮点和不足?小米Civi是一款没什么看点的手机,也就是雷军口中的线下机,空有一个漂亮的外表。其内在配置很一般。先来说它的外观吧,不管说小米Civi这套设计像vivo也好,还是像三星也好,至少这极米H3S和大眼橙X11,哪一款更值得购买?极米H3S和大眼橙X11,都属于5K档位的智能投影仪产品,有很多朋友在它们之间感觉难以取舍,总觉得这个很好,那个也不错,到底该买哪款才更适合呢?其实极米H3S,之前我也写过这款产品夏日炎炎,防晒该如何选择哈喽艾瑞巴蒂!都说养儿能防老,不,只有防晒才防老好吗!防晒不单单是防晒黑,防晒伤,更是防晒老!夏日炎炎,今天我就给大家分享一些必备的防晒系列的产品内容有点多,建议大家可以先收藏留着常戴钻戒有磨损?请收下这篇保养分享常常能听到身边结婚的朋友抱怨,买了钻戒不敢戴就怕不小心弄坏了,可是不戴又总感觉缺点啥心里不舒服。作为一个2003开始从事珠宝行业的老狗,到现在也有十几年的珠宝从业经验,现在就来教教从喝茶到懂茶再到了解茶文化,需要经历什么?我喝茶,但是不懂茶文化。我一直这么大言不惭地对各路友人宣称。因为于我而言,茶,只是饮品的一种。我喝它一是为了解渴,二是因为喜欢那个植物系的味道。至于它背后有什么样的故事,有多少历史