简体   繁体   English

无法将 awaitable 传递给 asyncio.run_coroutine_threadsafe

[英]Can't pass awaitable to asyncio.run_coroutine_threadsafe

I have observed that the asyncio.run_coroutine_threadsafe function does not accept general awaitable objects, and I do not understand the reason for this restriction.我观察到asyncio.run_coroutine_threadsafe函数不接受一般的可等待对象,我不明白这个限制的原因。 Observe观察

import asyncio


async def native_coro():
    return


@asyncio.coroutine
def generator_based_coro():
    return


class Awaitable:
    def __await__(self):
        return asyncio.Future()


loop = asyncio.get_event_loop()

asyncio.run_coroutine_threadsafe(native_coro(), loop)
asyncio.run_coroutine_threadsafe(generator_based_coro(), loop)
asyncio.run_coroutine_threadsafe(Awaitable(), loop)

Running this with Python 3.6.6 yields使用 Python 3.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

where line 24 is asyncio.run_coroutine_threadsafe(Awaitable(), loop) .其中第 24 行是asyncio.run_coroutine_threadsafe(Awaitable(), loop)

I know I can wrap my awaitable object in a coroutine defined like我知道我可以将我的可等待对象包装在一个定义如下的协程中

awaitable = Awaitable()

async def wrapper():
    return await awaitable

asyncio.run_coroutine_threadsafe(wrapper(), loop)

however my expectation was that the awaitable would be a valid argument directly to run_coroutine_threadsafe .但是我的期望是 awaitable 将直接成为run_coroutine_threadsafe的有效参数。

My questions are:我的问题是:

  1. What is the reason for this restriction?这个限制的原因是什么?
  2. Is the wrapper function defined above the most conventional way to pass an awaitable to run_coroutine_threadsafe and other APIs that demand an async def or generator-defined coroutine?上面定义的wrapper函数是将可等待run_coroutine_threadsafe传递给run_coroutine_threadsafe和其他需要async def定义或生成器定义的协程的 API 的最传统方法吗?

What is the reason for this restriction?这个限制的原因是什么?

Looking at the implementation , the reason is certainly not technical.实现来看,原因肯定不是技术上的。 Since the code already invokes ensure_future (rather than, say, create_task ), it would automatically work, and work correctly, on any awaitable object.由于代码已经调用了ensure_future (而不是,比如说create_task ),它会自动工作,并在任何可等待的对象上正常工作。

The reason for the restriction can be found on the tracker.限制的原因可以在跟踪器上找到。 The function was added in 2015 as a result of a pull request .作为pull request的结果,该功能于 2015 年添加。 In the discussion on the related bpo issue the submitter explicitly requests the function be renamed to ensure_future_threadsafe (in parallel to ensure_future ) and accept any kind of awaitable, a position seconded by Yury Selivanov.在有关bpo 问题的讨论中,提交者明确要求将函数重命名为ensure_future_threadsafe (与ensure_future并行)并接受任何类型的 awaitable,这是 Yury Selivanov 附议的立场。 However, Guido was against the idea:然而,Guido反对这个想法:

I'm against that idea.我反对这种想法。 I don't really see a great important future for this method either way: It's just a little bit of glue between the threaded and asyncio worlds, and people will learn how to use it by finding an example.无论哪种方式,我都没有真正看到这种方法的重要未来:它只是线程和异步世界之间的一点胶水,人们将通过查找示例来学习如何使用它。

[...] [...]

But honestly I don't want to encourage flipping back and forth between threads and event loops;但老实说,我不想鼓励线程和事件循环之间来回翻转; I see it as a necessary evil.我认为这是一种必要的罪恶。 The name we currently have is fine from the POV of someone coding in the threaded world who wants to hand off something to the asyncio world.我们目前拥有的名字来自一个在线程世界中编码的人的 POV,他想将某些东西交给 asyncio 世界。

Why would someone in the threaded world have an asyncio.future that they need to wait for?为什么线程世界中的某个人会有一个他们需要等待的 asyncio.future ? That sounds like they're mixing up the two worlds -- or they should be writing asyncio code instead of threaded code.这听起来像是他们混淆了两个世界——或者他们应该编写异步代码而不是线程代码。

There are other comments in a similar vein, but the above pretty much sums up the argument.还有其他类似的评论,但上面几乎总结了这个论点。

Is the wrapper function defined above the most conventional way to pass an awaitable to run_coroutine_threadsafe and other APIs that demand an async def or generator-defined coroutine?上面定义的wrapper函数是将可等待run_coroutine_threadsafe传递给run_coroutine_threadsafe和其他需要异步定义或生成器定义的协程的 API 的最传统方法吗?

If you actually need a coroutine object, something like wrapper is certainly a straightforward and correct way to get one.如果您确实需要一个协程对象,那么像wrapper东西肯定是一种直接且正确的获取方式。

If the only reason you're creating the wrapper is to call run_coroutine_threadsafe , but you're not actually interested in the result or the concurrent.futures.Future returned by run_coroutine_threadsafe , you can avoid the wrapping by calling call_soon_threadsafe directly:如果您创建包装器的唯一原因是调用run_coroutine_threadsafe ,但您实际上对结果或run_coroutine_threadsafe返回的concurrent.futures.Future不感兴趣,则可以通过直接调用call_soon_threadsafe来避免包装:

loop.call_soon_threadsafe(asyncio.ensure_future, awaitable)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 来自 asyncio.run_coroutine_threadsafe 的未来永远挂起? - Future from asyncio.run_coroutine_threadsafe hangs forever? Python Asyncio 没有使用 asyncio.run_coroutine_threadsafe 运行新的协程 - Python Asyncio is not running new coroutine using asyncio.run_coroutine_threadsafe Python asyncio loop.create_task 和 asyncio.run_coroutine_threadsafe 的区别 - Python asyncio difference between loop.create_task and asyncio.run_coroutine_threadsafe Python asyncio run_coroutine_threadsafe永不运行协程? - Python asyncio run_coroutine_threadsafe never running coroutine? 如何正确使用 asyncio run_coroutine_threadsafe 函数? - How to properly use asyncio run_coroutine_threadsafe function? Asyncio python - TypeError: A Future, a coroutine or an awaitable is required - Asyncio python - TypeError: A Future, a coroutine or an awaitable is required 类型错误:需要 asyncio.Future、协程或 awaitable - TypeError: An asyncio.Future, a coroutine or an awaitable is required loop.run_until_complete 给出“TypeError: An asyncio.Future, a coroutine or an awaitable is required” - loop.run_until_complete gives “TypeError: An asyncio.Future, a coroutine or an awaitable is required” loop.run_until_complete(g) 出错 An asyncio.Future, a coroutine or an awaitable is required - loop.run_until_complete(g) got error of An asyncio.Future, a coroutine or an awaitable is required 在单独的线程中执行 run_coroutine_threadsafe - Executing run_coroutine_threadsafe in a separate thread
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM