2015-09-02 48 views
1

我正在使用Python 3.4.3的龍捲風和電機。什麼時候會在函數調用堆棧中產生實際產量?

我有三個文件。讓我們將其命名爲像main.pymodel.pycore.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=>model.get=>core.get

core.get裝飾有@gen.coroutine和我打電話yield self.collection.find_one(params)print(result)打印None,但如果我返回結果,並嘗試在其打印的getLoggedIn函數中打印返回值。

我相信這與龍捲風的異步性質有關,打印在打印之前被調用,但我不確定。如果有人能夠在不同的可能情況下解釋協程/生成器的原理和行爲,這將是一個很大的幫助。

+0

'print(future)'做什麼? –

+0

我刪除了我以前的評論,因爲我現在看到這是你問題的一部分。你期望'結果=收益未來'做什麼?我認爲這將是一個語法錯誤。這並不令我感到意外;它給了「沒有」讓我感到驚訝。 'yield'的用法與'return'大致相似,但設置了一個生成器並保存了函數狀態。 –

+0

print(future)打印Future對象並打印(結果)打印無 – Mayank

回答

0

每次調用協程時都必須調用,調用者也必須是協程。所以getLoggedIn必須是一個協調程序,可以調用:

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

依此類推。有關詳細示例和說明,請參閱我的文章refactoring Tornado coroutines

+0

不僅如此,我很高興在這裏見到你;)。我從您的網站上的視頻教程開始了Motor + Tornado。在接受這個答案之前給我一段時間:) – Mayank

+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的異步性質不允許yieldprint之前運行,因爲您擔心。

最有可能的是,你的未來沒有返回任何東西,或者正在返回None(語義上相同,我知道)。 可能最好將result = yield future看作result = future.result()的專用版本

+0

集合沒有文檔,它會返回'None',這很好。我無法理解的是getLoggedIn()中的'result'將對象作爲'Future'。不應該是'None' – Mayank

+0

我能想到的唯一解釋是與此一致的是'model.Session.get'返回一個'Future'。通過打印,你已經有效地驗證'core.get'返回'None',而不是'Future'。 – sirosen

相關問題