Как в Tornado создать экземпляр класса асинхронно? Более менее разобрался(как мне кажется) с асинхронностью в торнадо, но при переписывании синхронного кода под торнадо возникла следующая проблема: Во время обработки запросов создаются экземпляры различных объектов:@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?
Для асинхронного создания экземпляра класса в Tornado, вы можете использовать фабричный метод или статический метод вместо конструктора класса.
Пример с использованием фабричного метода:class ObjClass:
@classmethod@gen.coroutine
def create(cls):
obj = cls()
yield obj.init()
raise gen.Return(obj)
@gen.coroutine
def init(self):
yield db.find({...})
Теперь вы можете создать экземпляр класса асинхронно в вашем коде следующим образом:obj = yield ObjClass.create()
Таким образом, вы сможете асинхронно выполнить необходимые операции во время создания экземпляра класса.