[Async-sig] async/sync library reusage

manuel miranda manu.mirandad at gmail.com
Thu Jun 8 18:32:06 EDT 2017


Hello everyone,

After using asyncio for a while, I'm struggling to find information about
how to support both synchronous and asynchronous use cases for the same
library.

I.e. imagine you have a package for http requests and you want to give the
user the choice to use a synchronous or an asynchronous interface. Right
now the approach the community is following is creating separate libraries
one for each version. This is far from ideal for several reasons, some I
can think of:

- Code duplication, most of the functionality is the same in both
libraries, only difference is the sync/async behaviors
- Some new async libraries lack functionality compared to their sync
siblings. Others will introduce bugs that the sync version already solved
long ago, etc.
- Different interfaces for the user for the same exact functionality.

In summary, in some cases it looks like reinventing the wheel. So now comes
the question, is there any documentation, guide on what would be best
practice supporting this kind of duality? I've been playing a bit with that
on my own but I really don't know if I'm doing something stupid or not.
Simple example:

"""
import asyncio


class MyConnector:

    @classmethod
    async def get(cls, key):
        return key


class AsyncClient:

    async def get(self, key):
        return await MyConnector.get(key)


class SyncClient:

    def __init__(self):
        self.loop = asyncio.get_event_loop()

    def get(self, key):
        return self.loop.run_until_complete(MyConnector.get(key))


def sync_call():
    client = SyncClient()
    print(client.get("sync_key"))


async def async_call():
    client = AsyncClient()
    print(await client.get("async_key"))


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(async_call())
    sync_call()
"""

This is in case the underlying connector is asynchronous already. If its
synchronous and you want to support both modes, you have to rewrite the IO
interactions of MyConnector into a new AsyncMyConnector to support asyncio
and then use one or the other accordingly in the upper classes.

Am I doing it right or there is another better/alternative way?

Thanks for your time,

Manuel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/async-sig/attachments/20170608/654dc3d6/attachment.html>


More information about the Async-sig mailing list