我想将作业从一个线程提交到一个asyncio事件循环(就像run_in_executor,但反过来说).
以下是asyncio文档中有关并发和多线程的内容:
要从不同的线程安排回调,应使用BaseEventLoop.call_soon_threadsafe()方法.从不同的线程安排协程的示例:
loop.call_soon_threadsafe(asyncio.async, coro_func())
这工作正常,但协程的结果丢失了.
相反,可以使用一个函数将完成的回调添加到async(或ensure_future)返回的未来,以便线程可以通过concurrent.futures.Future访问结果.
是否有特殊原因导致标准库中未实现此类功能?或者我错过了一种更简单的方法来实现这一目标?
我的问题或多或少是这样的,这实际上是一个 XY 问题导致了这个问题。然而,这不是重复的,因为我的用例略有不同,链接的线程没有回答我的问题。
我正在将一组同步程序从 Java 移植到 Python。这些程序与异步库交互。在 Java 中,我可以阻塞并等待该库的异步函数返回一个值,然后使用该值执行操作。
这是一个代码示例来说明问题。
def do_work_sync_1(arg1, arg2, arg3):
# won't even run because await has to be called from an async function
value = await do_work_async(arg1, arg2, arg3)
def do_work_sync_2(arg1, arg2, arg3):
# throws "Loop already running" error because the async library referenced in do_work_async is already using my event loop
event_loop = asyncio.get_event_loop()
event_loop.run_until_complete(do_work_async(arg1, arg2, arg3))
def do_work_sync_3(arg1, arg2, arg3):
# throws "got Future attached to a different loop" …Run Code Online (Sandbox Code Playgroud) 我观察到该asyncio.run_coroutine_threadsafe函数不接受一般的可等待对象,我不明白这种限制的原因。观察
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)
Run Code Online (Sandbox Code Playgroud)
使用 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
Run Code Online (Sandbox Code Playgroud)
第 24 行在哪里asyncio.run_coroutine_threadsafe(Awaitable(), loop)。
我知道我可以将我的可等待对象包装在一个定义如下的协程中
awaitable = Awaitable()
async def wrapper():
return await awaitable
asyncio.run_coroutine_threadsafe(wrapper(), …Run Code Online (Sandbox Code Playgroud)