[Python-ideas] Submitting a job to an asyncio event loop
Guido van Rossum
guido at python.org
Sun Sep 27 04:52:15 CEST 2015
I've read your write-up with interest. You're right that it's a bit awkward
to make calls from the threaded world into the asyncio world.
Interestingly, there's much better support for passing work off from the
asyncio event loop to a thread (run_in_executor()). Perhaps that's because
the use case there was obvious from the start: some things that may block
for I/O just don't have an async interface yet, so in order to use them
from an asyncio task they must be off-loaded to a separate thread or else
the entire event loop is blocked. (This is used for calling getaddrinfo(),
I'm curious where you have encountered the opposite use case?
I think if I had to do this myself I would go for a more minimalist
interface: something like your submit() method but without the call to
asyncio.coroutine(fn). Having the caller pass in the already-called
coroutine object might simplify the signature even further. I'm not sure I
see the advantage of trying to make this an executor -- but perhaps I'm
On Sat, Sep 26, 2015 at 7:29 AM, Vincent Michel <vxgmichel at gmail.com> wrote:
> I noticed there is currently no standard solution to submit a job from a
> thread to an asyncio event loop.
> Here's what the asyncio documentation says about concurrency and
> > To schedule a callback from a different thread, the
> BaseEventLoop.call_soon_threadsafe() method should be used.
> > Example to schedule a coroutine from a different thread:
> > loop.call_soon_threadsafe(asyncio.async, coro_func())
> The issue with this method is the loss of the coroutine result.
> One way to deal with this issue is to connect the asyncio.Future returned
> by async (or ensure_future) to a concurrent.futures.Future. It is then
> possible to use a subclass of concurrent.futures.Executor to submit a
> callback to an asyncio event loop. Such an executor can also be used to set
> up communication between two event loops using run_in_executor.
> I posted an implementation called LoopExecutor on GitHub:
> The repo contains the loopexecutor module along with tests for several use
> cases. The README describes the whole thing (context, examples, issues,
> It is interesting to note that this executor is a bit different than
> ThreadPoolExecutor and ProcessPoolExecutor since it can also submit a
> coroutine function. Example:
> with LoopExecutor(loop) as executor:
> future = executor.submit(operator.add, 1, 2)
> assert future.result() == 3
> future = executor.submit(asyncio.sleep, 0.1, result=3)
> assert future.result() == 3
> This works in both cases because submit always cast the given function to
> a coroutine. That means it would also work with a function that returns a
> Here's a few topic related to the current implementation that might be
> interesting to discuss:
> - possible drawback of casting the callback to a coroutine
> - possible drawback of concurrent.future.Future using
> - does LoopExecutor need to implement the shutdown method?
> - removing the limitation in run_in_executor (can't submit a coroutine
> - adding a generic Future connection function in asyncio
> - reimplementing wrap_future with the generic connection
> - adding LoopExecutor to asyncio (or concurrent.futures)
> At the moment, the interaction between asyncio and concurrent.futures only
> goes one way. It would be nice to have a standard solution (LoopExecutor or
> something else) to make it bidirectional.
> Python-ideas mailing list
> Python-ideas at python.org
> Code of Conduct: http://python.org/psf/codeofconduct/
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Python-ideas