Выход сопрограммы торнадо от другой сопрограммы постепенно - PullRequest
0 голосов
/ 12 июня 2018

Я хотел провести рефакторинг части моего приложения Tornado, поэтому я создал специальную функцию для возврата телефонных номеров:

@gen.coroutine
def get_phones(self, listname):
    phones = []
    logging.info("fetching phones")
    cursor = self._mongo.contacts.aggregate(self.get_query(
        subscription_filter={
            "$ne": [{"$ifNull": ["$$subscription.events.{listname}", None]}, None]
        },
        handler_filter={
            "handler.meta.is_active": True,
            "handler.meta.type": "phone"
        }
    ))
    try:
        while (yield cursor.fetch_next):
            contact = cursor.next_object()
            logging.info(contact)
            try:
                phones += [handler['subject'] for handler in contact['handlers']]
                if len(phones) > 50:
                    yield phones
                    phones = []
            except Exception:
                self._logger.warning("Could not get phone no")
    except Exception:
        phones = []
        logging.warning("Could not fetch contacts")

    if len(phones) > 0:
        yield phones

Что я хотел достичь с помощью асинхронного получения пакетов до 50контакты из моей БД и вернуть их вызывающей сопрограмме.

Это моя вызывающая сопрограмма:

@gen.coroutine
def on_heartbeat_status_update(self, status):
    phonegen = self.get_phones("ews:admin")
    logging.info(phonegen)
    while True:
        phones = yield phonegen
        logging.info(phones)
        if phones is None:
            break
        logging.info(len(phones))

Это не работает.«Телефоны» всегда отсутствуют.Может кто-нибудь предложить правильный способ достижения этого?Спасибо!

1 Ответ

0 голосов
/ 12 июня 2018

Вы должны использовать сопрограммы Python 3.6 для этой работы.Это была первая версия Python, которая поддерживала yield и await в одной и той же функции.Без этого система не сможет различить использование yield для сопрограммы и получение результата в качестве генератора.

Замените @gen.coroutine def на async def и используйте await cursor.fetch_next и yield phonesв get_phones.Тогда вы можете использовать async for phones in self.get_phones(...) в on_heartbeat_status_update.

...