Python Can';无法通过asyncio.run\u coroutine\u threadsafe等待
我注意到Python Can';无法通过asyncio.run\u coroutine\u threadsafe等待,python,python-asyncio,Python,Python Asyncio,我注意到asyncio.run\u coroutine\u threadsafe函数不接受一般的等待对象,我不理解这种限制的原因。观察 导入异步IO 异步def native_coro(): 返回 @异步协同程序 基于def生成器的def coro(): 返回 等待上课: 定义等待(自我): 返回asyncio.Future() loop=asyncio.get\u event\u loop() asyncio.run_coroutine_threadsafe(native_coro(),loo
asyncio.run\u coroutine\u threadsafe
函数不接受一般的等待对象,我不理解这种限制的原因。观察
导入异步IO
异步def native_coro():
返回
@异步协同程序
基于def生成器的def coro():
返回
等待上课:
定义等待(自我):
返回asyncio.Future()
loop=asyncio.get\u event\u loop()
asyncio.run_coroutine_threadsafe(native_coro(),loop)
asyncio.run\u coroutine\u threadsafe(基于生成器的\u coro(),循环)
asyncio.run\u coroutine\u threadsafe(waitiable(),循环)
在Python3.6.6中运行此功能会产生
Traceback (most recent call last):
File "awaitable.py", line 24, in <module>
asyncio.run_coroutine_threadsafe(Awaitable(), loop)
File "~/.local/python3.6/lib/python3.6/asyncio/tasks.py", line 714, in run_coroutine_threadsafe
raise TypeError('A coroutine object is required')
TypeError: A coroutine object is required
然而,我的期望是,等待将是一个有效的参数,直接用于run\u coroutine\u threadsafe
我的问题是:
wrapper
函数是否是传递可等待的运行\u coroutine\u threadsafe
和其他需要异步def
或生成器定义的coroutine的API的最传统方法sure\u future
(而不是说,create\u task
),它将自动在任何可等待的对象上工作,并且工作正常
限制的原因可以在跟踪器上找到。该功能是在2015年增加的,这是由于。在对相关问题的讨论中,提交人明确要求将该功能重命名为确保未来线程安全
(与确保未来
)并接受尤里·塞利万诺夫(Yury Selivanov)支持的任何形式的等待。然而,Guido的想法是:
我反对那个想法。不管怎样,我都不认为这种方法有着重要的未来:它只是线程和异步世界之间的一点粘合剂,人们将通过找到一个示例来学习如何使用它
[……]
但老实说,我不想鼓励在线程和事件循环之间来回翻转;我认为这是一种必然的罪恶。我们目前拥有的名称来自于一个在线程世界中编码的人的观点,他想把一些东西交给asyncio世界
为什么线程世界中的某个人需要等待asyncio.future?这听起来像是他们在混淆这两个世界——或者他们应该编写异步IO代码而不是线程代码
还有其他类似的评论,但上面的内容基本上概括了这一论点
上面定义的wrapper
函数是否是传递可等待的运行\u coroutine\u threadsafe
和其他需要异步def或生成器定义的coroutine的API的最传统方式
如果您确实需要一个协程对象,那么像wrapper
这样的东西肯定是一种简单而正确的方法
如果创建包装器的唯一原因是调用run\u coroutine\u threadsafe
,但实际上您对结果或run\u coroutine\u threadsafe
返回的concurrent.futures.Future
不感兴趣,可以通过直接调用call\u soon\u threadsafe
避免包装:
loop.call_soon_threadsafe(asyncio.ensure_future, awaitable)
放得好。为了举例说明为什么“线程世界中的某个人会有一个他们需要等待的[Waitable],我正在测试一个websocket服务器,我有多个客户端同时执行使用Robot框架执行的测试步骤。没有对执行上下文的控制意味着我无法使其全部异步。在我的情况下,我确实关心并发的.futures.Future,但用于
asyncio。确保将来的在其他地方很方便。@ChrisHunt我听到了。在我看来,run\u coroutine\u threadsafe
(和run\u in\u executor
在另一个方向)提供的功能是asyncio和经典同步/线程代码之间的奇妙粘合剂,对于将asyncio引入现有代码库非常重要。不幸的是,它被低估了,在asyncio介绍材料中经常被忽略。我理解其意图是鼓励尽可能多的代码成为“本地”基于协同程序的代码,但这不可能在一夜之间实现,在实现之前,需要有一种方便的方式让两者进行互操作。
loop.call_soon_threadsafe(asyncio.ensure_future, awaitable)