I've been recently trying to switch from a library using gevent to a library using asyncio. And do so without contaminating the whole code with the "async" keyword in one go.
As expected, calling the synchronous code from a coroutine is pretty straightforward. But the other way around is a bit more tricky. If the function is not running in the thread that runs the event loop, I can use something like this:
Which seems to work, despite the documentation saying that "If the future's result isn't yet available, raises InvalidStateError.".
But if the function that want to call a coroutine is in the thread that runs the event loop, then there's not much I can do to run a coroutine in the event loop that indirectly called that function.
As a somewhat more concrete example, let's consider a class that sends and receive messages:
class Client: async def on_msg(self, msg): process(msg)
async def asend(self, msg): print("async sending", msg) return len(msg) def send(self, msg): print("sending", msg) # return await self.asend(msg) async def run(self): await self.on_msg("PING")
# Some legacy code that indirectly ends up wanting to call: print("Received", msg) print(client.send("PONG"))
client = Client() asyncio.run(client.run())
Unless I missed something, it's pretty difficult to have
Client.asend without contaminating the whole code with
"async" and "await".
I only see two solutions right now.
process in a new thread and then
use the trick above. But running
process in a separate thread might
have some consequences since it doesn't expect it.
Client.send start a new event loop in a new thread. Which
might behave suprisingly when sharing file descriptors with the
What I'm proposing is to change a bit the behavior of
loop.run_until_complete as follow:
asyncio.run could be changed similarly.
There's of course a strong caveat that it's easy to create an infinite recursion with this. But I think it's worth it as it would allow a much easier integration of asyncio into existing code. Which (I think) limit its adoption.
What do you think about it?