欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Tornado路由與Application的實(shí)現(xiàn)

 更新時(shí)間:2023年05月16日 09:47:19   作者:tracy小貓  
本文主要介紹了Tornado路由與Application的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

路由原理

在Tornado框架中,路由是指將請(qǐng)求的URL映射到對(duì)應(yīng)的處理函數(shù)上,這個(gè)過(guò)程需要通過(guò)正則表達(dá)式來(lái)實(shí)現(xiàn)。Tornado使用了一種叫做Application的類來(lái)封裝整個(gè)Web應(yīng)用程序.我們定制一個(gè)Applicaiton繼承tornado的Application

from tornado.web import Application as tornadoApp
class Application(tornadoApp):
? ? """ 定制 Tornado Application 集成日志、sqlalchemy 等功能 """
? ? def __init__(self):
? ? ? ? self.ops_mongo = None ?# ops mongo
? ? ? ? self.redis_cluster = None ?# redis基礎(chǔ)session
? ? ? ? self.redis_manager = None ?# redis_manager session
? ? ? ? self.redis = None
? ? ? ? tornado_settings = {
? ? ? ? ? ? 'autoreload': settings.service.server.autoreload,
? ? ? ? ? ? 'debug': settings.service.server.debug,
? ? ? ? ? ? "default_handler_class": DefaultHandler,
? ? ? ? }
? ? ? ? route = getRoutes(settings)
? ? ? ? self.prepare()
? ? ? ? super(Application, self).__init__(handlers=route, **tornado_settings)
? ? def prepare(self):
? ? ? ? self.redis_cluster = asyncio.get_event_loop().run_until_complete(
? ? ? ? ? ? init_cluster()
? ? ? ? )
? ? ? ? self.ops_mongo = asyncio.get_event_loop().run_until_complete(
? ? ? ? ? ? init_ops_mongodb()
? ? ? ? )
? ? ? ? loop = asyncio.get_event_loop()
? ? ? ? self.redis = RedisPool(loop=loop).get_conn()
? ? ? ? self.redis_manager = RedisManager(self.redis)
? ? ? ? asyncio.get_event_loop().run_until_complete(
? ? ? ? ? ? create_all_indexes()
? ? ? ? )
? ? async def on_close(self, server_conn: object) -> None:
? ? ? ? await self.redis_manager.close()
? ? ? ? logger.info("close redis")
? ? ? ? self.ops_mongo.close()
? ? ? ? logger.info("close mongo")

這段代碼定義了一個(gè)繼承自 Tornado Application 的自定義 Application 類,并在初始化中進(jìn)行了一些準(zhǔn)備工作。

首先,定義了幾個(gè)實(shí)例變量,包括 ops_mongo(mongoDB 數(shù)據(jù)庫(kù)連接)、redis_cluster(基于 redis 的 session)、redis_manager(管理 redis 連接)和 redis(redis 數(shù)據(jù)庫(kù)連接)。

然后,根據(jù)配置文件中的設(shè)置,設(shè)定了 Tornado Application 的一些參數(shù),并根據(jù)路由設(shè)置得到路由列表。

接下來(lái),調(diào)用了 prepare 方法,該方法中通過(guò)異步方法初始化了 ops_mongo(mongoDB 數(shù)據(jù)庫(kù)連接)、redis_cluster(基于 redis 的 session)和 redis(redis 數(shù)據(jù)庫(kù)連接),并創(chuàng)建了 redis_manager 實(shí)例管理 redis 連接。最后,調(diào)用了異步方法 create_all_indexes,創(chuàng)建了所有的索引。
最后,定義了一個(gè)異步方法 on_close,在 Web 服務(wù)關(guān)閉時(shí)關(guān)閉了 redis_manager 實(shí)例和 ops_mongo 實(shí)例。同時(shí)加入了一些對(duì)于關(guān)閉的日志信息。

class DefaultHandler(tornado.web.RequestHandler):
? ? def get(self):
? ? ? ? raise tornado.web.HTTPError(
? ? ? ? ? ? status_code=404,
? ? ? ? ? ? reason="Not Found"
? ? ? ? )
? ? def write_error(self, status_code, exc_info=None, **kwargs):
? ? ? ? self.finish({"error": self._reason})
def getRoutes(setting):
? ? Routes = [
? ? ? ? (r"/redis", home.TestRedisHandler),
? ? ]
? ? return Routes

該代碼是使用 Tornado 框架定義一個(gè)繼承自 tornado.web.RequestHandler 的 DefaultHandler 類,包含兩個(gè)方法 get 和 write_error。

  • get 方法會(huì)拋出一個(gè) HTTPError,表示請(qǐng)求的頁(yè)面不存在或其他錯(cuò)誤,會(huì)返回一個(gè) 404 的狀態(tài)碼和 Not Found 的原因。
  • write_error 方法會(huì)在遇到未處理的異常時(shí)自動(dòng)調(diào)用,可以自定義錯(cuò)誤響應(yīng)的方式。這里定義的行為是結(jié)束響應(yīng)并返回一個(gè)包含錯(cuò)誤信息的 JSON 對(duì)象

另外,getRoutes 方法定義了一個(gè)以元組形式表示的 URL 路由表,將 /redis 映射到名為 TestRedisHandler 的類。

RequestHandler的功能

在Tornado中,RequestHandler是處理每個(gè)HTTP請(qǐng)求的基礎(chǔ)類,所有的請(qǐng)求處理類都應(yīng)該繼承自它。RequestHandler有如下幾個(gè)常用的方法:

  • initialize():初始化方法,在請(qǐng)求處理類實(shí)例化時(shí)自動(dòng)調(diào)用,用于設(shè)置一些參數(shù)或進(jìn)行一些初始化操作。
  • prepare():在處理請(qǐng)求前調(diào)用,用于進(jìn)行一些安全檢查、身份驗(yàn)證等操作,并且可以自定義錯(cuò)誤頁(yè)面。
  • get()、post()等:根據(jù)HTTP請(qǐng)求方式的不同,提供相應(yīng)的get()、post()等方法來(lái)處理請(qǐng)求,并返回相應(yīng)的HTTP響應(yīng)。
  • write()、finish():用于返回響應(yīng)數(shù)據(jù),并結(jié)束請(qǐng)求處理。
  • redirect()、set_header()等:提供一些常用的HTTP響應(yīng)輔助方法。
class BaseHandler(RequestHandler, ABC):
????traceid = None
????start_time = None
????# 普通返回
????response_dict = {'code': 0, 'message': "", 'tid': "", 'data': None}
????# 分頁(yè)返回
????response_page_dict = {'code': 0, 'message': "", 'tid': "", 'data': None, "pagination":
????????{"pagesize": 0, "pages": 0, "items": 0, "pageno": 0}
??????????????????????????}
????@classmethod
????def return_response(cls):
????????resp = AttrDict(cls.response_dict)
????????return resp
????@classmethod
????def return_page_response(cls):
????????resp = AttrDict(cls.response_page_dict)
????????return resp
????@classmethod
????def create_page(cls, response: AttrDict, total=None, pagesize=0, pageno=None):
????????response.pagination["items"] = total
????????response.pagination["pagesize"] = pagesize
????????response.pagination["pages"] = total // pagesize if total % pagesize == 0 else total // pagesize + 1
????????response.pagination["pageno"] = pageno
????????return response
????def get_request(self):
????????request_body = None
????????if self.request.body:
????????????request_body = tornado.escape.json_decode(self.request.body)
????????return request_body
????def return_json(self, response):
????????*"""*
**返回統(tǒng)一的*json*格式結(jié)果
*****:param*** *response:*
*"""*
** ?
**self.set_header("Content-Type", "application/json; charset=UTF-8")
????????self.response_dict = json.dumps(response, default=json_util.default)
????????self.write(self.response_dict)
????def prepare(self):
????????trace_id = self.request.headers.get("tid", None)
????????self.__class__.start_time = datetime.datetime.now()
????????if not trace_id:
????????????trace_id = str(uuid.uuid4())
????????????self.request.headers["tid"] = trace_id
????????self.__class__.traceid = trace_id
????def write_error(self, status_code, exc_info=None, api_code=None, **kwargs):
????????resp = self.return_response()
????????resp.code = status_code
????????resp.tid = self.traceid
????????ex = exc_info[1]
????????if isinstance(ex, Exception):
????????????err_msg = str(ex)
????????????resp.message = err_msg
????????if isinstance(ex, tornado.web.HTTPError):
????????????err_msg = str(ex)
????????????resp.message = err_msg
????????if isinstance(ex, tornado.web.HTTPError) and ex.log_message:
????????????err_msg = str(ex.log_message)
????????????resp.message = err_msg
????????self.response_dict = json.dumps(resp, default=json_util.default)
????????self.finish(resp)
????def on_finish(self):
????????# 處理完請(qǐng)求后輸出日志,將請(qǐng)求頭信息和響應(yīng)結(jié)果json化
????????end_time = datetime.datetime.now()
????????request_data = {
????????????"tid": self.request.headers.get("tid", None),
????????????"url": self.request.uri,
????????????"method": self.request.method,
????????????"remote_ip": self.request.remote_ip,
????????????"user_agent": self.request.headers["User-Agent"],
????????????"request_body": json.loads(self.request.body) if self.request.body else ""
????????}
????????response_data = {
????????????"status": self.get_status(),
????????????"response_body": json.loads(self.response_dict) if not isinstance(self.response_dict,
??????????????????????????????????????????????????????????????????????????????dict) else self.response_dict,
????????????"response_time": (end_time - self.start_time).microseconds / 1000
????????}
????????logger = get_logger("access")
????????logger.bind(**request_data).bind(**response_data).info("request success")

BaseHandler 的類,它繼承了 tornado.web.RequestHandler 和 abc.ABC 兩個(gè)類。該類提供了一些基礎(chǔ)方法,可以被繼承使用來(lái)構(gòu)建業(yè)務(wù)處理類。

這個(gè)類定義了兩種返回方式:普通返回和分頁(yè)返回。普通返回返回的數(shù)據(jù)格式有 code、message、tid 和 data 四個(gè)字段,其中 code 表示請(qǐng)求狀態(tài)碼,message 表示請(qǐng)求狀態(tài)消息,tid 表示請(qǐng)求追蹤 id,data 表示響應(yīng)數(shù)據(jù)。分頁(yè)返回在普通返回的基礎(chǔ)上加入了分頁(yè)參數(shù)信息,即 pageSize、pages、items 和 pageNo。

該類實(shí)現(xiàn)了三個(gè)類方法:return_response、return_page_response 和 create_page。return_response 返回普通返回的響應(yīng)對(duì)象,return_page_response 返回分頁(yè)返回的響應(yīng)對(duì)象,create_page 用于創(chuàng)建分頁(yè)響應(yīng)。

該類實(shí)現(xiàn)了三個(gè)實(shí)例方法:get_request、return_json 和 write_error。get_request 方法用于獲取請(qǐng)求體的 json 數(shù)據(jù),return_json 方法用于返回 json 格式的響應(yīng),write_error 方法用于處理請(qǐng)求出錯(cuò)時(shí)返回的響應(yīng)。

該類實(shí)現(xiàn)了兩個(gè)鉤子函數(shù):prepare 和 on_finish。prepare 在請(qǐng)求進(jìn)入處理前被調(diào)用,可以用來(lái)獲取請(qǐng)求頭信息等,on_finish 在請(qǐng)求處理完后被調(diào)用,用于記錄日志等操作。

處理錯(cuò)誤

在Tornado中,異常處理同樣也是一個(gè)非常重要的問(wèn)題,異常處理可以讓我們?cè)谟龅藉e(cuò)誤時(shí)能夠有更好的反應(yīng)和處理??梢酝ㄟ^(guò)使用@tornado.web.appadvice()裝飾器或者重寫write_error()方法來(lái)進(jìn)行自定義錯(cuò)誤處理。

import tornado.web
class CustomErrorHandler(tornado.web.RequestHandler):
????def write_error(self, status_code, **kwargs):
????????if self.settings.get("serve_traceback"):
????????????self.write('Some Exception occurs: {}'.format(kwargs['exc_info'][1]))
????????else:
????????????self.write('Some Exception occurs. We are on it!')
????????self.set_status(status_code)
class ErrorExample(tornado.web.RequestHandler):
????def get(self, error_printer):
????????if error_printer == "raise":
????????????raise Exception("An unknown error occurred.")
????????elif error_printer == "syntax":
????????????raise SyntaxError("There is a syntax error in your code.")
????????else:
????????????self.write("This is normal operation!")

上述代碼中,使用write_error()重寫了RequestHandler的默認(rèn)錯(cuò)誤處理方式。當(dāng)我們?cè)L問(wèn)http://localhost:8888/err?error=syntax 時(shí),會(huì)輸出 Some Exception occurs: There is a syntax error in your code

處理完成

tornado的RequestHandler是用于請(qǐng)求處理的基本類,其中on_finish是RequestHandler的一個(gè)方法,可以在請(qǐng)求處理完成后被調(diào)用。當(dāng)客戶端請(qǐng)求處理完成時(shí),可以使用此方法進(jìn)行一些清理工作或日志記錄等操作,并將tornado 對(duì)象釋放回底層IOLoop。在on_finish方法內(nèi)可以進(jìn)行資源釋放、統(tǒng)計(jì)請(qǐng)求處理時(shí)間等工作。此外,在建立連接之前初始化某些對(duì)象或資源,也可以在on_finish方法中完成清理。

以下是RequestHandler的on_finish方法的聲明:

def on_finish(self) -> None:
????????"""
????????Finish this response, ending the HTTP request.
????????"""
????????pass

Tornado提供了很多的錯(cuò)誤處理接口來(lái)幫助我們進(jìn)行異常處理。為了使Web程序更加的健壯,我們需要盡可能的考慮到各種可能出現(xiàn)的錯(cuò)誤情況,并對(duì)異常情況進(jìn)行適當(dāng)?shù)奶幚怼?/p>

到此這篇關(guān)于Tornado路由與Application的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Tornado路由與Application內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python實(shí)現(xiàn)sublime3的less編譯插件示例

    python實(shí)現(xiàn)sublime3的less編譯插件示例

    這篇文章主要介紹了python實(shí)現(xiàn)sublime3的less編譯插件示例的相關(guān)資料
    2014-04-04
  • 在arcgis使用python腳本進(jìn)行字段計(jì)算時(shí)是如何解決中文問(wèn)題的

    在arcgis使用python腳本進(jìn)行字段計(jì)算時(shí)是如何解決中文問(wèn)題的

    這篇文章主要介紹了在arcgis使用python腳本進(jìn)行字段計(jì)算時(shí)是如何解決中文問(wèn)題的,需要的朋友可以參考下
    2015-10-10
  • 控制Python浮點(diǎn)數(shù)輸出位數(shù)的操作方法

    控制Python浮點(diǎn)數(shù)輸出位數(shù)的操作方法

    在python的輸出結(jié)果中,尤其是浮點(diǎn)數(shù)的輸出,當(dāng)我們需要寫入文本文件時(shí),最好是采用統(tǒng)一的輸出格式,這樣也能夠增強(qiáng)結(jié)果的可讀性,這篇文章主要介紹了控制Python浮點(diǎn)數(shù)輸出位數(shù)的方法,需要的朋友可以參考下
    2022-04-04
  • Python實(shí)現(xiàn)合成多張圖片到PDF格式

    Python實(shí)現(xiàn)合成多張圖片到PDF格式

    在日常生活中,經(jīng)常會(huì)遇到需要提交身份證正反面證明資料的情況,而且這些網(wǎng)站大部分只接受pdf格式,這時(shí)候我們就需要把身份證正反面兩張圖片合成為一個(gè)pdf文件。本文將為大家提供用Python實(shí)現(xiàn)這一要求的方法,需要的可以參考一下
    2022-02-02
  • python實(shí)現(xiàn)與redis交互操作詳解

    python實(shí)現(xiàn)與redis交互操作詳解

    這篇文章主要介紹了python實(shí)現(xiàn)與redis交互操作,結(jié)合實(shí)例形式分析了Python Redis模塊的安裝、導(dǎo)入、連接與簡(jiǎn)單操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2020-04-04
  • Python中使用bidict模塊雙向字典結(jié)構(gòu)的奇技淫巧

    Python中使用bidict模塊雙向字典結(jié)構(gòu)的奇技淫巧

    bidict模塊通過(guò)一對(duì)一映射結(jié)構(gòu)的處理為Pyhton帶來(lái)雙向字典,能夠更加利用Python的切片功能,這里我們就來(lái)學(xué)習(xí)Python中使用bidict模塊雙向字典結(jié)構(gòu)的奇技淫巧:
    2016-07-07
  • Python 通過(guò)分隔符分割文件后按特定次序重新組合的操作

    Python 通過(guò)分隔符分割文件后按特定次序重新組合的操作

    這篇文章主要介紹了Python 通過(guò)分隔符分割文件后按特定次序重新組合的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • Windows 平臺(tái)做 Python 開發(fā)的最佳組合(推薦)

    Windows 平臺(tái)做 Python 開發(fā)的最佳組合(推薦)

    在 Windows 上如何做 Python 開發(fā)呢?相信大神們都會(huì)有自己的解決方案,但本文希望介紹微軟官方發(fā)布的 Terminal 和 Visual Studio Code,希望它們能構(gòu)建更流暢的 Windows 開發(fā)體驗(yàn),感興趣的朋友跟隨小編一起看看吧
    2020-07-07
  • Pandas加速代碼之避免使用for循環(huán)

    Pandas加速代碼之避免使用for循環(huán)

    如果你使用Python和Pandas進(jìn)行數(shù)據(jù)分析,循環(huán)是不可避免要使用的。這篇文章主要給大家介紹了關(guān)于Pandas加速代碼之避免使用for循環(huán)的相關(guān)資料,需要的朋友可以參考下
    2021-05-05
  • python?離散點(diǎn)圖畫法的實(shí)現(xiàn)

    python?離散點(diǎn)圖畫法的實(shí)現(xiàn)

    本文主要介紹了python?離散點(diǎn)圖畫法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04

最新評(píng)論