Reputation: 2095
I have some code with this structure:
def my_callback():
loop = asyncio.get_event_loop()
return loop.run_until_complete(my_coroutine_2())
async def my_coroutine_2():
return await my_stuff.some_future
async def my_coroutine():
not_my_code.library_function(my_callback)
Inside my_callback
, which the library_function
calls, I need to access and run coroutine code.
However, run_until_complete
produces an error: Event loop already running!
.
Is it possible to accomplish what's described above?
That is to say, is there an ordinary function call which will cause the event loop to pause whatever coroutine is currently executing (i.e. the caller of loop.run_until_complete()
), and continue executing other coroutines (including the one passed to run_until_complete()
) until the requested coroutine is finished, in which case the ordinary function un-blocks?
I've thought that maybe threads could help, but as I understand it, all coroutines have to belong to the same thread.
How do I do this? Is it possible?
Upvotes: 0
Views: 718
Reputation: 154856
Assuming the external library is thread-safe, you can invoke its function off-thread using run_in_executor
. While waiting for the function to finish, the current coroutine will be blocked, but the event loop will keep running.
When the your callback is invoked from another thread, it can use run_coroutine_threadsafe
to submit the coroutine to the (still fully functional) event loop, and report the result back to the library:
async def my_coroutine():
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, not_my_code.library_function,
lambda: my_callback(loop))
def my_callback(loop):
return asyncio.run_coroutine_threadsafe(my_coroutine_2(), loop)
Upvotes: 1