Более менее разобрался(как мне кажется) с асинхронностью в торнадо, но при переписывании синхронного кода под торнадо возникла следующая проблема:
Во время обработки запросов создаются экземпляры различных объектов:
@gen.coroutine
def prepare(self):
....
obj = ObjClass()
...
, при этом выполняются запросы в базу, которые хотелось бы выполнять асинхронно:
class ObjClass:
def __init__(self):
...
db.find({...})
...
Первое что пришло в голову - добавить во всех классах дополнительную инициализацию (если не вообще убрать __init__), в которую вынести все что требуется сделать асинхронным:
class ObjClass:
def __init__(self):
...
@gen.coroutine
def init(self):
...
db.find({...})
...
@gen.coroutine
def prepare(self):
....
obj = yield ObjClass().init()
...
Но хочется написать что-то вроде:
class ObjClass:
@gen.coroutine
def __init__(self):
...
yield db.find({...})
...
@gen.coroutine
def prepare(self):
....
obj = yield ObjClass()
...
Попытался покопать в сторону метаклассов и переопределения __call__, но выражение вроде
yield obj.__init__(*args, **kwargs)
не работает, поскольку __init__ в классе упорно не хочет становиться генератором с
class ObjClass:
@gen.coroutine
def __init__(self):
...
yield db.find({...})
...
Есть какая-то скрытая магия в интерпретаторе, через которую не протащить корутину?
Как еще можно асинхронно создать экземпляр в Tornado?