从MotorEngine异步查询中获取结果

时间:2014-09-23 10:53:20

标签: python tornado tornado-motor

为了异步数据库访问,我试图在我的Tornado应用程序中使用MotorEngine切换MongoEngine,到目前为止,我无处可去。

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 个答案:

答案 0 :(得分: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,而不是一个值。您必须等待Future通过产生它来解析为某个值:

ret = yield userMethods.get_all_users()

有关从协同程序调用协同程序的更多信息,请参阅我的"Refactoring Tornado Coroutines"

顺便说一下,你可以用“gen.coroutine”装饰“get”,它比“异步”和“gen.engine”更现代,但两种风格都有效。

答案 1 :(得分:0)

只是一个建议。如果您希望每次使用其方法时都避免创建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)
...