Let's say I have BaseClass
which contains some logic in main_function()
which is common for both SyncClass
and AsyncClass
. Let's say those 2 classes have their unique implementation of get_data()
and the former gets in synchronous manner, while the latter in asynchronous manner. I have written something like this and it seems to work:
class BaseClass:
def get_data():
pass
@gen.coroutine
def main_function():
# some logic
try:
data = yield self.get_data()
except:
data = self.get_data()
# some more logic
class SyncClass(BaseClass):
def get_data():
//makes sync call to Mongo and gets data (using Mongoengine)
class AsyncClass(BaseClass):
@gen.coroutine
def get_data():
//makes async call to Mongo and gets data (using Motorengine)
I used this code as a workaround, because I already had those methods for get_data() implemented that way. Is there some more elegant solution? There are 2 parts of my code that concern me:
try:
data = yield self.get_data()
except:
data = self.get_data()
I would prefer not to use try/except here.
The other thing is: I have @gen.coroutine
in the AsyncClass
while the same function isn't decorated with @gen.coroutine
in the BaseClass
.
Thank you!
Synchronous and asynchronous methods have different interfaces (that's what it means to be asynchronous). AsyncClass.get_data
returns a Future
; SyncClass.get_data
does not. If this were in a statically-typed language, these two methods would not be able to implement the same abstract method from the base class. Of course, Python is more flexible and does not restrict you in this way, but the caller still needs to either know which kind of method it's dealing with or be prepared to find out via try/except
or isinstance
checks, etc. (note that try/except is dangerous in this case, because yield
in a tornado coroutine will accept things like lists and dicts)
In general, you cannot transparently switch between them as you're hoping to do here. Remember that any function that may call yield self.get_data()
also needs to be decorated with @coroutine
, so once one part of your system is asynchronous, it starts to spread. It's usually best to embrace this trend and just make things asynchronous.