当前位置: 首页 > 知识库问答 >
问题:

Python asyncio:isinstance((基于生成器的coroutune),???)==真的?

景元忠
2023-03-14

两种打字方式我都不知道。等待的集合。abc。Awaitable涵盖一个基于生成器的协同路由,它是中定义的Awaitable之一

  • https://www.python.org/dev/peps/pep-0492/#await-expression

从Python 3.6开始,几个asyncioAPI,如睡眠()open_connection()实际上返回基于生成器的协程。我通常对它们的返回值应用wait关键字没有问题,但是我要处理正常值和可等待值的混合,我需要弄清楚哪些需要wait才能产生实际值。

这是我的问题,什么满足isinstance(c,??)==对于任意基于生成器的协同例程c,是否为True?我并不是坚持使用isinstance来达到这个目的,也许getattr()是一个解决方案。。。

我正在开发一个小的模拟实用程序,用于基于的异步函数的单元测试https://blog.miguelgrinberg.com/post/unit-testing-asyncio-code它内部有一个异步。模拟返回值的Queue(),我想增强我的实用程序,以便队列可以有可等待的元素,每个元素都触发wait操作。我的代码看起来像

async def case01(loop):
  f = AsyncMock()
  f.side_effect = loop, []
  await f()  # blocks forever on an empty queue

async def case02(loop):
  f = AsyncMock()
  f.side_effect = loop, ['foo']
  await f() # => 'foo'
  await f() # blocks forever

async def case03(loop):
  f = AsyncMock()
  f.side_effect = loop, [asyncio.sleep(1.0, 'bar', loop=loop)]
  await f() # yields 'bar' after 1.0 sec of delay

出于可用性原因,我不想手动用create\u task()包装返回值。

我不确定我的队列是否会合法地包含正常的非协程生成器;然而,理想的解决方案应该能够区分正常的生成器和基于生成器的协程,并跳过对前者应用wait操作。

共有2个答案

壤驷志学
2023-03-14
匿名用户

检测可以传递给wait的对象的有文档记录的方法是使用inspect。可等待。

根据PEP 492,await需要一个可等待的对象,该对象可以是:

  • 本机协程-使用异步定义定义的Python函数
  • 基于生成器的协同例程-一个用类型装饰的Python生成器。协同程序
  • Python类的实例,该类定义了wait
  • 将tp\u实现为异步的扩展类型的实例。am_等待

is实例(o,collections.abc.可等待的)涵盖了除第二个之外的所有内容。如果没有明确记录,这可能会被报告为可等待的中的错误,指向inspect.isawaitable以检查所有可等待的对象。

请注意,您无法通过检查类型来区分基于生成器的协程对象和常规的生成器-迭代器。两者具有完全相同的类型,因为协程装饰器不会包装给定的生成器,它只是在其代码对象上设置一个标志。检查对象是否是基于生成器的协程生成的生成器-迭代器的唯一方法是检查其代码标志,即inspect.isawaitable是如何实现的。

一个相关的问题是为什么Awaable只检查__await__的存在,而不检查wait本身使用的其他机制。这对于试图使用Awaable来检查对象的实际可等待性的代码来说是不幸的,但这并非没有先例。可迭代性和IterableABC之间存在类似的差异:

class Foo:
  def __getitem__(self, item):
      raise IndexError

>>> iter(Foo())
<iterator object at 0x7f2af4ad38d0>
>>> list(Foo())
[]

尽管Foo的实例是可iterable的,isinstance(Foo(),collections)。abc。Iterable)返回false。

卢英范
2023-03-14

我不确定您在这里尝试测试什么,但检查模块具有检查大多数内容的功能,如下所示:

>>> async def f(c):
...     await c
>>> co = f()
>>> inspect.iscoroutinefunction(f)
True
>>> inspect.iscoroutine(co)
True
>>> inspect.isawaitable(co)
True

最后两种方法的不同之处在于,isawaitable适用于您可以等待的任何事情,而不仅仅是协同路由。

如果您真的想用iInstance进行测试:

isinstance(f)只是类型。FunctionType,这不是很有用。要检查它是否是返回协同例程的函数,还需要检查其标志:f.\uu code\uuuuu。co_标志

isinstance(co)是类型。您可以对其进行测试,但这可能仍然不是一个好主意。

 类似资料:
  • 我正在寻找一个随机数生成器,我可以创建一个种子,并采取两个输入x和y来生成数字。每次使用相同的输入和相同的种子时,我都需要相同的数字。 我正在使用这个来随机分配一个坐标网格上的纹理,所以我需要它每次都是一样的。所以每次我在x=100,y=120的时候,在同一个种子里,我需要相同的随机数,所以相同的纹理被分配在那个点上。

  • 我是JavaFx的新手,我正在使用Intellij和SceneBuilder。我创建了一个MVC模型: PersonOverview和RootLayout由SceneBuilder生成。 个人概述:

  • 当我使用Spring framework时,我经常看到2个术语基于Java和基于注释的配置/自动生成。 如果它们不一样,你能告诉我它们之间有什么不同吗?

  • 如何生成版本1(基于时间的)UUID?是否有一个单独的库,或者它是如何在Java7 API中提供的,我错过了它。

  • 本文向大家介绍PHP实现基于文本的摩斯电码生成器,包括了PHP实现基于文本的摩斯电码生成器的使用技巧和注意事项,需要的朋友参考一下 最近遇到一个基于输入文本生成摩斯代码音频文件的需求。几番搜索无果之后,我决定自己编写一个生成器。 因为我希望通过web的方式访问我的摩斯代码音频文件,所以我决定采用PHP作为我主要的编程语言。上面的截图显示了一个开始生成莫斯代码的网页。在下载的zip文件中,包含了用于

  • 我是Xtext和Xtend的新手,正在尝试使用Xtext文档中的Xtext教程学习Xtext。我正在使用Xtext 2.14在Java10下运行Eclipse光子。我刚开始学习扩展教程,很早就遇到了一个问题。以下是我尝试使用代码生成器的代码: 这是我的语法文件: 我的问题是Eclipse说@Inject注释有问题,它说,这是在一个Eclipse Xtext项目中根据教程中的说明生成的。 我该如何从