Issue
I have a code like the foolowing:
def render():
loop = asyncio.get_event_loop()
async def test():
await asyncio.sleep(2)
print("hi")
return 200
if loop.is_running():
result = asyncio.ensure_future(test())
else:
result = loop.run_until_complete(test())
When the loop
is not running is quite easy, just use loop.run_until_complete
and it return the coro result but if the loop is already running (my blocking code running in app which is already running the loop) I cannot use loop.run_until_complete
since it will raise an exception; when I call asyncio.ensure_future
the task gets scheduled and run, but I want to wait there for the result, does anybody knows how to do this? Docs are not very clear how to do this.
I tried passing a concurrent.futures.Future
calling set_result
inside the coro and then calling Future.result()
on my blocking code, but it doesn't work, it blocks there and do not let anything else to run. ANy help would be appreciated.
Solution
To implement runner
with the proposed design, you would need a way to single-step the event loop from a callback running inside it. Asyncio explicitly forbids recursive event loops, so this approach is a dead end.
Given that constraint, you have two options:
- make
render()
itself a coroutine; - execute
render()
(and its callers) in a thread different than the thread that runs the asyncio event loop.
Assuming #1 is out of the question, you can implement the #2 variant of render()
like this:
def render():
loop = _event_loop # can't call get_event_loop()
async def test():
await asyncio.sleep(2)
print("hi")
return 200
future = asyncio.run_coroutine_threadsafe(test(), loop)
result = future.result()
Note that you cannot use asyncio.get_event_loop()
in render
because the event loop is not (and should not be) set for that thread. Instead, the code that spawns the runner thread must call asyncio.get_event_loop()
and send it to the thread, or just leave it in a global variable or a shared structure.
Answered By - user4815162342
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.