当前位置: 首页 > 面试题库 >

Python原生协程和send()

束高雅
2023-03-14
问题内容

基于生成器的协程具有一种send()方法,该方法允许调用方和被调用方之间进行双向通信,并从调用方恢复生成的生成协程。这是将生成器变成协程的功能。

尽管新的本机async/await协程为异步I /
O提供了出色的支持,但我看不出如何获得与之等效的协程send()。明确禁止使用yieldinasync函数,因此本机协程只能使用一条return语句返回一次。尽管await表达式将新值带入协程中,但这些值来自被调用方,而不是调用方,并且等待的调用从每次开始就进行评估,而不是从中断的地方进行评估。

有没有办法从中断的地方恢复返回的协程并可能发送新值?如何使用本地协程在David
Beazley的“协程与并发性好奇课程”中模拟这些技术?

我想到的一般代码模式是这样的

def myCoroutine():
  ...
  while True:
    ...
    ping = yield(pong)
    ...

并在呼叫者中

while True:
  ...
  buzz = myCoroutineGen.send(bizz)
  ...

编辑

我接受了凯文(Kevin)的回答,但我注意到PEP说

协程内部基于生成器,因此它们共享实现。与生成器对象类似,协程具有throw(),send()和close()方法。

协程的throw(),send()方法用于将值推入并向类似Future的对象中引发错误。

因此,显然本地协程确实有一个send()?没有yield表达式来接收协程内部的值如何工作?


问题答案:

有没有办法从中断的地方恢复返回的协程并可能发送新值?

没有。

async并且await 句法糖yield from。当协程返回(带有return语句)时,就是这样。框架不见了。它不可恢复。这正是发电机始终工作的方式。例如:

def foo():
    return (yield)

您可以这样做f = foo(); next(f); f.send(5),然后您将返回5。但是,如果f.send()再次尝试,它将不起作用,因为您已经从框架中返回了。 f不再是现场发电机。

现在,就新的协程而言,据我所知,似乎在事件循环与某些基本谓词(例如)之间的通信中保留了yield和send
asyncio.sleep()。协程产生asyncio.Future直到事件循环的对象,并且一旦关联操作完成(它们通常通过call_soon()和其他事件循环方法进行调度),事件循环会将那些相同的将来对象发送回协程。

您可以通过等待它们来产生将来的对象,但这不是像.send()was那样的通用接口。它专门供事件循环实现使用。如果您没有实现事件循环,则可能不想玩这个循环。如果您
正在 实现一个事件循环,你需要问自己为什么完美的实现中asyncio不足以达到你的目的,并解释 明确 你正在尝试做之前,我们可以帮助你。

请注意,这yield from是不建议使用的。如果您想要的协程根本不与事件循环绑定,请改用它。
asyncawait在专门为事件循环异步编程设计。如果这不是你在做什么,然后asyncawait都开始与错误的工具。

还有一件事:

yield明确禁止在异步函数中使用in,因此本机协程只能使用一条return语句返回一次。

await表达式 可以 控制产量。 await something()完全类似于yield from something()。他们只是更改了名称,所以对于不熟悉发电机的人来说将更加直观。

对于那些实际上对实现自己的事件循环感兴趣的人,这里有一些示例代码,展示了(非常少的)实现。此事件循环极为简化,因为它被设计同步运行某些特殊编写的协程,就像它们是正常功能一样。它不能提供您期望从真正的BaseEventLoop实现中获得的全面支持,并且对于与任意协程一起使用也不安全。

通常,我会将代码包含在我的答案中,而不是链接到该代码,但是存在版权问题,它对答案本身并不重要。



 类似资料:
  • 网络爬虫(又称为网页蜘蛛,网络机器人,在 FOAF 社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。

  • 与子程序(或者说函数)一样,协程(coroutine)也是一种程序组件。Donald Knuth 曾说,子程序是协程的特例。 一个子程序就是一次函数调用,它只有一个入口,一次返回,调用顺序是明确的。但协程的调用和子程序则大不一样,协程允许有多个入口对程序进行中断、继续执行等操作。 Python2 可以通过 yield 来实现基本的协程,但不够强大,第三方库 gevent 对协程提供了强大的支持。另

  • 前言 百度已经于近日上线了全站 HTTPS 的安全搜索,默认会将 HTTP 请求跳转成 HTTPS。本文重点介绍 HTTPS 协议 ,并简单介绍部署全站 HTTPS 的意义。 HTTPS 协议概述 HTTPS 可以认为是 HTTP + TLS。HTTP 协议大家耳熟能详了,目前大部分 WEB 应用和网站都是使用 HTTP 协议传输的。 TLS 是传输层加密协议,它的前身是 SSL 协议,最早由 n

  • 问题内容: 如何使协程停止超时? 我不明白为什么asyncio.wait_for()对我不起作用。我有这样的一段代码(计划实现telnet客户端的实现): 正如我认为的那样,在某些时候(在await语句中)将控制返回到事件循环。我认为应该在没有更多数据要接收时发生。如果事件循环具有控制权,则它可以随着超时而停止。 但是,如果服务器没有发送任何有用的信息(匹配的信息),我的代码就会在此循环中迷路,就

  • 操作系统的设计,可以归结为三点: 以多进程形式,允许多个任务同时运行; 以多线程形式,允许将单个任务分成多个子任务运行; 提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。 本章主要介绍在 Python 中如何进行进程和线程编程等,主要有以下几个方面: 进程 线程 ThreadLocal 协程 参考资料 进程和线程 - 廖雪峰的官方网站 进程与线程的一个简

  • 我有一个用Kotlin(android studio)编写的android应用程序和用React Native编写的应用程序的UI。我的问题是这些能联系在一起吗?如果是,怎么做?还有,你们能发布一些我可以通过的链接吗。 附注:我对react Native一无所知。