I'm building a wrapper for an API. For now, it works. However, it is synchronous, using the requests module for HTTP calls.
I would like to implement a way to asynchronously call these methods while not having to use a different name or lib version. I immediately thought about overloading, but seeing as overloading in python is a bit different than other languages, it doesn't really look possible.
Essentially, I want to build a class that would look like this (idea-wise, I know that it doesn't work in Python):
class Foo:
def foo(self):
# Requests code...
print("foo sync")
async def foo(self):
# aiohttp code...
print("foo async")
And use it in this way:
f = Foo()
f.foo()
await f.foo()
Output:
>> "foo sync"
>> "foo async"
Essentially, in this code, the async function would just completely override the previous one, which isn't really helpful.
From some googling, it doesn't exactly look possible, however, Python always manages to surprise me.
Thanks in advance :D
Question: Overloading asynchronous methods
Consider the following class
definitions, using Inheritance
with Overloading
!
You have a Base class Foo:
from which inherits class Foo_async(Foo):
.
Therefore you can reuse most of your implementation, in sync
and async
mode.
The class Foo_async
mainly implements only the async/await
requirements.
Note: I'm using asyncio
. For example:
import asyncio
class Foo():
def __init__(self):
self.mode = "sync"
def __repr__(self):
return "{}::foo() {}".format(self.__class__.__name__, self.mode)
def foo(self):
print("{}".format(self.__repr__()))
print("\t\tworkload {}".format(1))
print("\t\tworkload {}".format(2))
class Foo_async(Foo):
def __init__(self):
self.mode = "async awaited"
async def foo(self):
super().foo()
Usage:
async def run(foo):
await foo.foo()
if __name__ == '__main__':
Foo().foo()
loop = asyncio.get_event_loop()
loop.run_until_complete(run(Foo_async()))
loop.close()
Output:
Foo::foo() sync workload 1 workload 2 Foo_async::foo() async awaited workload 1 workload 2
If you want more granularity, split the workload in def foo(...)
into seperate workload functions.
Now you are able to call this functions using await
.
For example: (Show, only changed code!)
class Foo():
...
def foo(self):
print("{}".format(self.__repr__()))
self.workload_1()
self.workload_2()
def workload_1(self):
print("\t\t{} workload {}".format(self.mode, 1))
def workload_2(self):
print("\t\t{} workload {}".format(self.mode, 2))
class Foo_async(Foo):
...
async def foo(self):
print("{}".format(self.__repr__()))
await self.workload_1()
await self.workload_2()
async def workload_1(self):
super().workload_1()
async def workload_2(self):
super().workload_2()
Output:
Foo::foo() sync sync workload 1 sync workload 2 Foo_async::foo() async awaited async awaited workload 1 async awaited workload 2
Tested with Python:3.5.3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With