首頁 後端開發 Python教學 使用tornado的coroutine進行編程

使用tornado的coroutine進行編程

Oct 17, 2016 pm 02:13 PM

在tornado3發布之後,強化了coroutine的概念,在非同步程式設計中,取代了原來的gen.engine, 變成現在的gen.coroutine。這個裝飾器本來就是為了簡化在tornado中的非同步程式設計。避免寫回呼函數, 使得開發更符合正常邏輯思考。一個簡單的例子如下:


class MaindHandler(web.RequestHandler):

   @asynchronous

   yncHTTPClient()

       resp = yield client .fetch(https://api.github.com/users")

       if resp.code == 200:

          resp = escape.json_decode p. (json.dumps(resp, indent=4, separators=(',', ':')))

       else:

           resp = {"message": "errornrite fp. json.dumps(resp, indent =4, separators={',', ':')))

       self.finish()

在yield語句之後,ioloop將會註冊該事件,等到resp 這個過程是異步的。這裡使用json.dumps,而沒有使用tornado自帶的escape.json_encode,是因為在建立REST風格的API的時候,往往會從瀏覽器存取取得JSON格式的資料。 ,在瀏覽器端顯示查看的時候會更友善。的回答escape並不打算提供全部的json功能,使用者可以自己直接使用json模組。必須使用異步的函式庫。庫可以在這裡找到。包括用的比較多的MongoDB的Driver。

在3.0版本之後,gen.coroutine模組顯得比較突出。 coroutine裝飾器可以讓原本靠回呼的非同步程式看起來像是同步程式設計。其中便是利用了Python中生成器的Send函數。在生成器中,yield關鍵字往往會與正常函數中的return相比。它可以被當成迭代器,從而使用next()傳回yield的結果。但是生成器還有另一個用法,就是使用send方法。在生成器內部可以將yield的結果賦值給一個變量,而這個值是透過外部的生成器client來send的。舉個例子:

def test_yield():

   pirnt "test yeild"

   says = (yield)

"__main__":

   client = test_yield ()

   client.next()


   client.send("hello world")

輸出結果如下:


test yeildello它的client使用send方法,原來函數繼續運作。而這裡的gen.coroutine方法就是非同步執行所需的操作,然後等待結果回傳之後,再send到原函數,原函數則會繼續執行,這樣就以同步方式寫的程式碼達到了非同步執行的效果。

Tornado非同步程式設計


使用coroutine實現函數分離的非同步程式設計。具體如下:

@gen.coroutine

def post(self):

   client = AsyncHTTPClient()

   client = AsyncHTTPClient()

  

   if resp == 200:

       body = escape.json_decode(resy.body)

          logger.error("client fetch error % d, %s" % (resp.code, resp.message))


   self.write(escape.json_encode(body))

   self.finish()


;

@gen.coroutime

def post(self):

   resp = yield GetUser()

   self.write(resp)

   self.write(resp):

   client = AsyncHTTPClient()

   resp = yield client.fetch("https://api.github.com/users")

   if resp.code == 200:p else:

       resp = {"message": "fetch client error"}

       logger.error("client fetch error %d, %s" resp. (resp)

這裡,當把非同步封裝在一個函數中的時候,並不是像普通程式那樣使用return關鍵字進行返回,gen模組提供了一個gen.Return的方法。是透過raise方法實現的。這個也是和它是使用生成器方式實現有關的。


使用coroutine跑定時任務


Tornado中有這麼一個方法:


tornado.ioloop.IOLitime)阻塞版本,它接受一個時間長度和一個函數這兩個參數。表示多少時間之後呼叫該函數。在這裡它是基於ioloop的,因此是非阻塞的。此方法在客戶端長連接以及回調函數程式設計中使用的比較多。但是用它來跑一些定時任務卻是無奈之舉。通常跑定時任務也沒必要使用到它。但是我在使用heroku的時候,發現沒有註冊信用卡的話僅僅能夠使用一個簡單Web Application的託管。不能加入定時任務來跑。於是就想出這麼一個方法。在這裡,我主要使用它隔一段時間透過Github API介面去抓取資料。大自使用方法如下:


裝飾器


 def sync_loop_call(delta=60 *​​ 1000):

.

 """

     def wrap_loop(func):

         @wraps(func)

         @gen.coroutine

.       options.logger.info("function %r start at %d" %

                                 (func.__name__, int(time.time())))         yield func(*args, **kwargs)

             except Exception, e:  r error: %s" %

                                   "function %r end at %d" %

                                 (func.__name__, int(time.time)) ))           wrap_func)

         return wrap_func

     return wrap_loop

     return wrap_loop

(delta=10 * 1000)

 def worker():

     """

     Do something

__  name__ == "__main__":

 worker()

 app.listen(options.port)

 tornado.ioloop.IOLoop.instance().start()

這樣做之後,當Web Application啟動之後,定時任務就會隨著跑起來,而且因為它是基於事件的,並且非同步執行的,所以並不會影響Web服務的正常運行,當然任務不能是阻塞的或計算密集型的。我這裡主要是抓取數據,而且用的是Tornado自帶的非同步抓取方法。


在sync_loop_call裝飾器中,我在wrap_func函數上加了@gen.coroutine裝飾器,這樣就保證只有yeild的函數執行完之後,才會執行add_timeout操作。如果沒有@gen.coroutine裝飾器。那麼不等到yeild返回,就會執行add_timeout了。

完整地例子可以參考我的Github,這個專案搭建在heroku上。用於展示Github用戶活躍度排名和用戶區域分佈。可以存取Github-Data查看。由於國內heroku被牆,需要翻牆才能進入。

總結


Tornado是一個非阻塞的web伺服器以及web框架,但是在使用的時候只有使用異步的庫才會真正發揮它異步的優勢,當然有些時候因為App本身要求並因為App本身要求不是很高,如果不是阻塞特別嚴重的話,也不會有問題。另外使用coroutine模組進行非同步程式設計的時候,當把一個功能封裝到一個函數中時,在函數運行中,即使出現錯誤,如果沒有去捕捉的話也不會拋出,這在調試上顯得非常困難。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何解決Linux終端中查看Python版本時遇到的權限問題? 如何解決Linux終端中查看Python版本時遇到的權限問題? Apr 01, 2025 pm 05:09 PM

Linux終端中查看Python版本時遇到權限問題的解決方法當你在Linux終端中嘗試查看Python的版本時,輸入python...

在Python中如何高效地將一個DataFrame的整列複製到另一個結構不同的DataFrame中? 在Python中如何高效地將一個DataFrame的整列複製到另一個結構不同的DataFrame中? Apr 01, 2025 pm 11:15 PM

在使用Python的pandas庫時,如何在兩個結構不同的DataFrame之間進行整列複製是一個常見的問題。假設我們有兩個Dat...

如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎? 如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎? Apr 02, 2025 am 07:18 AM

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

Uvicorn是如何在沒有serve_forever()的情況下持續監聽HTTP請求的? Uvicorn是如何在沒有serve_forever()的情況下持續監聽HTTP請求的? Apr 01, 2025 pm 10:51 PM

Uvicorn是如何持續監聽HTTP請求的? Uvicorn是一個基於ASGI的輕量級Web服務器,其核心功能之一便是監聽HTTP請求並進�...

Python中如何通過字符串動態創建對象並調用其方法? Python中如何通過字符串動態創建對象並調用其方法? Apr 01, 2025 pm 11:18 PM

在Python中,如何通過字符串動態創建對象並調用其方法?這是一個常見的編程需求,尤其在需要根據配置或運行...

哪些流行的Python庫及其用途? 哪些流行的Python庫及其用途? Mar 21, 2025 pm 06:46 PM

本文討論了諸如Numpy,Pandas,Matplotlib,Scikit-Learn,Tensorflow,Tensorflow,Django,Blask和請求等流行的Python庫,並詳細介紹了它們在科學計算,數據分析,可視化,機器學習,網絡開發和H中的用途

如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到? 如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到? Apr 02, 2025 am 07:15 AM

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

See all articles