我正在使用python 3.4.3中的龙卷风和电机。
我有三个文件。可以将其命名为main.py
,model.py
,core.py
我有三个功能,每个功能一个......
main.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
model.py
@classmethod
def get(cls, db, user_id=None, **kwargs):
session = core.Session(db)
return session.get(user_id, **kwargs)
core.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
=&gt; model.get
=&gt; core.get
core.get以@gen.coroutine
修饰,我致电yield self.collection.find_one(params)
print(result)
打印None
,但如果我返回结果并尝试在getLoggedIn
函数中打印返回值,则会打印出来。
我认为这与龙卷风的异步性质有关,而印刷品在收益前被调用,但我不确定。如果有人能够在不同的情况下解释协程/发电机的原理和行为,那将是一个很大的帮助。
答案 0 :(得分:1)
PEP 255涵盖了生成器的原始规范。
但是,tornado
以非常具体的方式在协同程序中使用yield
:http://www.tornadoweb.org/en/stable/guide/coroutines.html#how-it-works
你的代码看起来并不像普通的生成器,因为生成器的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()
答案 1 :(得分:0)
必须提供对协程的每次调用,并且调用者也必须是协程。所以getLoggedIn必须是一个调用的协程:
result = yield model.Session.get(db, uid=uid)
等等。有关详细示例和解释,请参阅我在refactoring Tornado coroutines上的文章。