[Async-sig] async/sync library reusage

Luciano Ramalho luciano at ramalho.org
Thu Jun 8 20:07:22 EDT 2017


Hello, Manuel.

The answer to your problem is to refactor the libraries in the "sans I/O"
style.

Take a look here:
http://sans-io.readthedocs.io/


On Thu, 8 Jun 2017 at 19:32 manuel miranda <manu.mirandad at gmail.com> wrote:

> 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
> _______________________________________________
> Async-sig mailing list
> Async-sig at python.org
> https://mail.python.org/mailman/listinfo/async-sig
> Code of Conduct: https://www.python.org/psf/codeofconduct/
>
-- 
Luciano Ramalho
|  Author of Fluent Python (O'Reilly, 2015)
|     http://shop.oreilly.com/product/0636920032519.do
|  Technical Principal at ThoughtWorks
|  Twitter: @ramalhoorg
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/async-sig/attachments/20170609/63a69d06/attachment.html>


More information about the Async-sig mailing list