1

我正在 python 3.4.3 中研究龙卷风和电机。

我得到了三个文件。让我们将其命名为main.py, model.py,core.py

我有三个功能,每个功能...

主文件

def getLoggedIn(request_handler):
    # request_handler = tornado.web.RequestHandler()
    db = request_handler.settings["db"]
    uid = request_handler.get_secure_cookie("uid")
    result = model.Session.get(db, uid=uid)
    return result.get("_id", None) if result else None

模型.py

@classmethod
    def get(cls, db, user_id=None, **kwargs):
        session = core.Session(db)
        return session.get(user_id, **kwargs)

核心.py

@gen.coroutine
    def get(self, user_id, **kwargs):
        params = kwargs
        if user_id:
            params.update({"_id": ObjectId(user_id)}) #This does not exist in DB
        future = self.collection.find_one(params)
        print(future) #prints <tornado.concurrent.Future object at 0x04152A90>
        result = yield future
        print(result) #prints None
        return result

调用看起来像getLoggedIn => model.get => core.get

core.get 被装饰,@gen.coroutine我调用Prints但如果我返回结果并尝试在函数中打印返回值,yield self.collection.find_one(params)print(result)会打印。NonegetLoggedIn

我相信这与龙卷风的异步性质有关,打印在产量之前被调用,但我不确定。如果有人可以解释协程/生成器在不同可能情况下的原理和行为,那将是一个很大的帮助。

4

2 回答 2

1

PEP 255涵盖了生成器的原始规范。但是,以非常具体的方式在协程内部使用:tornadohttp ://www.tornadoweb.org/en/stable/guide/coroutines.html#how-it-worksyield

您的代码看起来或闻起来都不像普通的生成器,因为 Python 的生成器概念正在被tornado用来定义协程。我会说你并不真正想要生成器编写的原理,而是龙卷风生成器的原理——一个完全不同的野兽。

分配 的值yield是包装@gen.coroutine装饰器将未来的结果传递回core.get. 这样,result不会分配未来对象,而是future.result().

yield future本质上暂停您的函数并将其转换为future将调用的回调,在yield. 正如您所担心的那样,它的异步性质tornado不允许在yield之前运行。print

最有可能的是,您的 Future 没有返回任何东西,或者正在返回None(我知道,语义上等价)。最好将其result = yield future视为一个专门的版本result = future.result()

于 2015-09-02T15:47:14.767 回答
0

对协程的每次调用都必须产生,调用者也必须是协程。所以 getLoggedIn 必须是一个调用的协程:

result = yield model.Session.get(db, uid=uid)

等等。有关详细示例和说明,请参阅我关于重构 Tornado 协程的文章。

于 2015-09-02T22:08:45.873 回答