為什麼 Tornado 在調用 self.finish() 以後不終止 RequestHandler 中相關處理函數的運行?
一個很簡單的程序:
import tornado.ioloop
import tornado.webclass MainHandler(tornado.web.RequestHandler):def get(self):
self.finish() self.write("Hello, world")application = tornado.web.Application([(r"/", MainHandler),
])if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()如果我們訪問的話,Tornado會報錯,Trackback如下:
Traceback (most recent call last):
File "C:Python27libsite-packages ornadoweb.py", line 927, in _execute getattr(self, self.request.method.lower())(*args, **kwargs) File "I:party est.py", line 9, in get self.write("Hello, world")File "C:Python27libsite-packages ornadoweb.py", line 442, in write
assert not self._finishedAssertionErrorERROR:root:Cannot send error response after headers written很顯然,在我們調用self.finish()以後,RequestHandler的處理函數繼續向下執行了,從而導致了錯誤的發生。
那麼,為什麼在調用self.finish()以後,Tornado不自動終止函數的執行呢?另外,知乎對這種情況是怎麼處理的?我現在的做法是在self.redirect()以後加一句return,不知道合適不合適。self.redirect內部同樣調用了self.finish,也會出現這樣的問題。而且對於用戶來說,執行self.redirect以後發送Location Header,用戶就被跳轉走了,繼續執行是沒有意義的。
self.finish()代表回應生成的終結,並不代表著請求處理邏輯的終結。假設你有一個block的邏輯是和回應無關的,那麼放在self.finish()的後面可以顯著的縮短響應時間。
所以,如果你確定自己的邏輯需要立即返回,可以在self.finish()後立刻return。Tornado在將這個自由留給了你自己。
另外一個理由是,在call stack里讓頂端的函數去彈出一個非頂端的函數,這個邏輯有點奇怪。唯一能夠提供退出的機制就是異常了。但是在正常邏輯裡面使用異常去實現一個功能,也是很怪的邏輯。沒錯 同理還有self.render/self.write 我們在所有這種response語句前加return 例如 return self.redirect(/)
想要終止函數運行,可以拋出Finish()異常
from tornado.web import Finish
...
...
class IndexHandler(RequestHandler):
def get(self):
self.write("Hello")
raise Finish()
self.write("World")
為什麼finish 後要終止函數運行呢? finnish 以後你可以做任何其他的事情,做self.write 錯誤 是因為和前端的此次http 交互結束了,做其他事情還是可以的。
推薦閱讀:
※portal.azure.com這個網站是怎麼做出來的?
※flask WEB開發第八章測試登錄的問題,builtins.TypeError,求大神賜教?
※記住密碼功能如何設計?
※從事網頁前端開發工作的人員英語發音都那麼奇怪嗎?
※如何評價beego框架?
TAG:Web開發 | Python | Tornado | Web伺服器軟體 | 計算機網路 | Python框架 |