Получить результат из асинхронного запроса MotorEngine

Я пытаюсь переключить MongoEngine с MotorEngine в моем приложении Tornado ради асинхронного доступа к БД, и до сих пор я не получил ничего.

query

@gen.coroutine
    def get_all_users(self):
        users = yield User.objects.find_all()

handler

class IUser(BaseHandler):
    @asynchronous
    @gen.engine
    def get(self,userId=None, *args, **kwargs):
        try:
            userMethods = UserMethods()
            sessionId = self.request.headers.get('sessionId')
            ret = userMethods.get_all_users()
        except Exception as ex:
            print str(ex)

        self.finish()

Когда я печатаю ret переменная это говорит <tornado.concurrent.Future object at 0x7fb0236fe450>, Если я попытаюсь напечатать ret.result() это никуда меня не приведет.

Любая помощь приветствуется, так как я борюсь со всем, что я думаю...

2 ответа

Решение

get_all_users должен как-то вернуть его значение. В Python 2.6 или 2.7 генераторы не могут использовать оператор return, поэтому сопрограммы имеют специальное исключение "Return":

@gen.coroutine
def get_all_users(self):
    users = yield User.objects.find_all()
    raise gen.Return(users)

В Python 3.3 и более поздних версиях вы можете просто "возвращать пользователей".

Теперь в "get" вызов get_all_users только дает вам ожидающее будущее, а не значение. Вы должны подождать, пока Future не разрешит значение, передав его:

ret = yield userMethods.get_all_users()

Для получения дополнительной информации о вызове сопрограмм из сопрограмм см. Мой "Рефакторинг сопрограмм Торнадо".

Кстати, вы можете украсить "get" просто "gen.coroutine", он более современный, чем "asynchronous" и "gen.engine", но любой стиль работает.

Просто предложение. Если вы хотите избежать создания экземпляра userMethods при каждом использовании его метода:

userMethods = UserMethods()

Вы можете использовать @classmethod Декоратор, прежде чем объявить это:

class UserMethods():
    pass

@classmethod
@tornado.gen.coroutine
def get_all_users(self):
    users = yield User.objects.find_all()
    raise gen.Return(users)

## class IUser
...

try:
    # userMethods = UserMethods()   --not necesary now--
    sessionId = self.request.headers.get('sessionId')
    ret = yield userMethods.get_all_users()
except Exception as ex:
    print str(ex)
...
Другие вопросы по тегам