摘要:這是我重新復(fù)習(xí)的原因放棄了之前自己實現(xiàn)的全面擁抱的這個改動是非常大的而且閱讀的源碼可以發(fā)現(xiàn)其中大部分函數(shù)都支持了類型檢驗和返回值提示值得閱讀
廢話不多說,直接上代碼
__auth__ = "aleimu" __doc__ = "學(xué)習(xí)tornado6.0+ 版本與python3.7+" import time import asyncio import tornado.gen import tornado.web import tornado.ioloop import tornado.httpserver # tornado的HTTP服務(wù)器實現(xiàn) from tornado.options import define, options from tornado.httpclient import HTTPClient, AsyncHTTPClient from requests import get settings = {"debug": True} url = "http://127.0.0.1:5000/" # 這是另個服務(wù),請求5s后返回結(jié)果 # RuntimeError: Cannot run the event loop while another loop is running # 解釋:HTTPClient內(nèi)部寫 loop.run_xxx,因為那是啟動event loop的命令,通常只再最最最外面用一次,之后的代碼都應(yīng)假設(shè) loop 已經(jīng)在運轉(zhuǎn)了。 def synchronous_fetch(url): print("synchronous_fetch") try: http_client = HTTPClient() time.sleep(5) response = http_client.fetch(url) print(response.body) except Exception as e: print("Error: " + str(e)) return str(e) http_client.close() return response.body # 替代synchronous_fetch的同步請求,沒有內(nèi)置loop.run_xxx def synchronous_get(url): response = get(url) time.sleep(5) print("synchronous_fetch") return response.text # 簡單的模擬異步操作,這里之后應(yīng)該替換成各種異步庫的函數(shù) async def sleep(): print("start sleep") await asyncio.sleep(5) print("end sleep") # 異步請求 async def asynchronous_fetch(url): http_client = AsyncHTTPClient() response = await http_client.fetch(url) print("asynchronous_fetch") return response.body # 測試 class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world:%s" % self.request.request_time()) self.finish() print("not finish!") return # 同步阻塞 class synchronous_fetcher(tornado.web.RequestHandler): def get(self): self.write("%s,%s" % (synchronous_fetch(url), self.request.request_time())) # 同步阻塞 class synchronous_geter(tornado.web.RequestHandler): def get(self): self.write("%s,%s" % (synchronous_get(url), self.request.request_time())) # 異步阻塞,我以為curl "127.0.0.1:8888/1" 總耗時希望為5s,可是是25s,看來異步?jīng)]搞好,以下的函數(shù)都是基于此改進(jìn)的 class asynchronous_fetcher_1(tornado.web.RequestHandler): async def get(self): body = await asynchronous_fetch(url) for i in range(3): print("skip %s" % i) await tornado.gen.sleep(5) time.sleep(5) print("end request") self.write("%s,%s" % (body, self.request.request_time())) # curl "127.0.0.1:8888/1" # b"{ "data": "123" } ",25.026000022888184 # 異步阻塞,效果同上,這里只是證明 tornado.gen.sleep(5)和asyncio.sleep(5) 效果一致 class asynchronous_fetcher_2(tornado.web.RequestHandler): async def get(self): body = await asynchronous_fetch(url) # 關(guān)注協(xié)程完成后返回的結(jié)果 for i in range(3): print("skip %s" % i) await sleep() time.sleep(5) print("end request") self.write("%s,%s" % (body, self.request.request_time())) # curl "127.0.0.1:8888/2" # b"{ "data": "123" } ",25.039999961853027 # 異步非阻塞-將部分異步操作放入組中,實現(xiàn)loop管理 class asynchronous_fetcher_3(tornado.web.RequestHandler): async def get(self): body = await asynchronous_fetch(url) await asyncio.wait([sleep() for i in range(3)]) print("end request") self.write("%s,%s" % (body, self.request.request_time())) # curl "127.0.0.1:8888/3" # b"{ "data": "123" } ",10.001000165939331 # 異步非阻塞-將所有異步操作放入組中,實現(xiàn)loop管理 class asynchronous_fetcher_4(tornado.web.RequestHandler): async def get(self): task_list = [sleep() for i in range(3)] task_list.append(asynchronous_fetch(url)) body = await asyncio.wait(task_list) # 將所有異步操作的結(jié)果返回,但是是無序的,要是需要返回結(jié)果的話解析起來比較麻煩 print("end request:", body) # print(type(body), len(body),type(body[0]),len(body[0]),type(body[0])) self.write("%s,%s" % ([x.result() for x in body[0] if x.result() is not None][0], self.request.request_time())) # curl "127.0.0.1:8888/4" # b"{ "data": "123" } ",5.006999969482422 def make_app(): return tornado.web.Application([ (r"/", MainHandler), (r"/1", asynchronous_fetcher_1), (r"/2", asynchronous_fetcher_2), (r"/3", asynchronous_fetcher_3), (r"/4", asynchronous_fetcher_4), (r"/5", synchronous_fetcher), (r"/6", synchronous_geter), ], **settings) if __name__ == "__main__": print("server start!") app = make_app() server = tornado.httpserver.HTTPServer(app) server.bind(8888) server.start(1) # forks one process per cpu,windows上無法fork,這里默認(rèn)為1 tornado.ioloop.IOLoop.current().start()總結(jié)
1.Tornado使用單線程事件循環(huán),寫的不好,會阻塞的非常嚴(yán)重,比如synchronous_geter 2.flask+celery可以完成常見的異步任務(wù) 3.await語法只能出現(xiàn)在通過async修飾的函數(shù)中 4.可以看到tornado.gen.coroutine, tornado.concurrent.run_on_executor,tornado.web.asynchronous,tornado.gen.coroutine等這些裝飾器都不在經(jīng)常使用了,都由async和await代替參考文檔:
https://zhuanlan.zhihu.com/p/27258289 # Python async/await入門指南 http://www.tornadoweb.org/en/stable/guide/intro.html # 這個官網(wǎng) https://www.osgeo.cn/tornado/guide/intro.html #Tornado 1.0 - Tornado 6.0的更新說明,以及6.0版本的中文文檔,適合英語不好的人閱讀 https://www.osgeo.cn/tornado/releases/v5.0.0.html# 在Python 3上, IOLoop 總是包裝asyncio事件循環(huán)。
On Python 3, IOLoop is always a wrapper around the asyncio event loop.
這是我重新復(fù)習(xí)tornado的原因,tornado放棄了之前自己實現(xiàn)的tornado.ioloop,全面擁抱asyncio的event_loop.這個改動是非常大的,
而且閱讀tornado的源碼可以發(fā)現(xiàn)其中大部分函數(shù)都支持了類型檢驗,和返回值提示,值得閱讀.
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/43783.html
摘要:臆想的針對讀取到的內(nèi)容進(jìn)行操作,比如打印文件內(nèi)容臆想中,讀取文件是有返回值的,將返回值,即文件內(nèi)容,賦給一個變量,然后決定對讀取到的內(nèi)容進(jìn)行相應(yīng)的操作,例如打印文件中的內(nèi)容。 臆想的 let fs = require(fs) function readFile(filename){ ... } let content = readFile(config.js) // 針對讀...
摘要:項目的主要運行部分,采集器驗證器打分檢測等功能實現(xiàn)的模塊。在中可以配置異步的并發(fā)量等來控制驗證器。調(diào)用有了穩(wěn)定的高分代理數(shù)據(jù),那么就可以掛起一個為我們的爬蟲保駕護(hù)航,這一部分可以單獨拿出來編寫,使用其他框架之類的都是不錯的選擇。 FooProxy 穩(wěn)健高效的評分制 IP代理池 + API服務(wù)提供,可以自己插入采集器進(jìn)行代理IP的爬取,支持 MongoDB 4.0 使用 Python3....
摘要:項目的主要運行部分,采集器驗證器打分檢測等功能實現(xiàn)的模塊。在中可以配置異步的并發(fā)量等來控制驗證器。調(diào)用有了穩(wěn)定的高分代理數(shù)據(jù),那么就可以掛起一個為我們的爬蟲保駕護(hù)航,這一部分可以單獨拿出來編寫,使用其他框架之類的都是不錯的選擇。 FooProxy 穩(wěn)健高效的評分制 IP代理池 + API服務(wù)提供,可以自己插入采集器進(jìn)行代理IP的爬取,支持 MongoDB 4.0 使用 Python3....
摘要:我們使用單元測試來驗證一下我們使用了配合做單元測試。我們編寫相應(yīng)的單元測試你會發(fā)現(xiàn),如果出現(xiàn)異常,只是簡單的返回。但是在上面異常拋出的時候,解釋器已經(jīng)不在中了,因此無法被捕獲。 譯者按: 錯誤是無法避免的,妥善處理它才是最重要的! 原文: A Guide to Proper Error Handling in JavaScript Related Topics: 譯者: Funde...
摘要:談起閉包,它可是兩個核心技術(shù)之一異步基于打造前端持續(xù)集成開發(fā)環(huán)境本文將以一個標(biāo)準(zhǔn)的項目為例,完全拋棄傳統(tǒng)的前端項目開發(fā)部署方式,基于容器技術(shù)打造一個精簡的前端持續(xù)集成的開發(fā)環(huán)境。 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老鳥,不論是面試求職,還是日...
閱讀 4033·2021-11-22 13:53
閱讀 1735·2021-09-23 11:52
閱讀 2454·2021-09-06 15:02
閱讀 975·2019-08-30 15:54
閱讀 915·2019-08-30 14:15
閱讀 2398·2019-08-29 18:39
閱讀 670·2019-08-29 16:07
閱讀 433·2019-08-29 13:13