@avigmati

Как выполнить асинхронный запрос к mongo, используя motor, в __init__ методе класса?

Есть такой код:
def __init__(self):
        uri = 'mongodb://{}/{}'.format(kwargs['metrika_db_host'], kwargs['metrika_db_name'])
        client = motor.motor_tornado.MotorClient(uri)
        self.db = client.get_default_database()

        # падает с ошибкой TypeError: __init__() should return None, not 'generator'
        colls = yield self.db.collection_names()
        for c in colls:
            print('c: ', c)

Я так понял, что init метод должен возвращать None и, видимо, colls = yield self.db.collection_names() возвращает объект Future который генератор.
Тем не менее, хочется, например, создать коллекции именно в __init__().
Как сделать сие?
Попробовал инициировать в методе __new__():
def __new__(cls, *args, **kwargs):
        print(cls, args, kwargs)
        uri = 'mongodb://{}/{}'.format(kwargs['metrika_db_host'], kwargs['metrika_db_name'])
        client = motor.motor_tornado.MotorClient(uri)
        print(client)
        cls.db = client.get_default_database()
        print(cls.db) # до этого момента все ок
        colls = yield cls.db.collection_names()  # зависает на этой строке
        for c in colls:
            print('c: ', c)
        return BaseCrawl.__new__(cls)
  • Вопрос задан
  • 497 просмотров
Решения вопроса 1
@766dt
Возникал у меня как-то похожий вопрос.

Методы вроде __init__ или __new__ вызываются как синхронные __внутри__ питона, поэтому, судя по всему, нет достаточно простой и красивой возможности выполнить их асинхронно. Судя по тому, что появляются специальные магические методы, которые могут содержать асинхронный код, асинхронный код в обычныx методах не предусмотрен изначально.
Можно выполнить инициализацию без асинхронности, используя что-то вроде asyncio.gather() или BaseEventLoop.run_until_complete(), но это бессмысленно, т.к. заблокирует остальные задачи.

Я сейчас, в случае необходимости, делаю два метода инициализации, __init__() в котором всё что можно по быстрому выполнить синхронно, и init() который уже асинхронный. Некрасиво,
yield from Class().init()
, но более явно.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы