從tornado的 Hello,world 開始分析tornado的源碼
python import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
application = tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
很容易可以看出,通過繼承
RequestHandler
類定義自己的處理類,來處理請求。Application類的對象來處理URI的路由(将URI
r"/"
于處理類
MainHandler
組成tuple,關聯起來)。
tornado.web.Application類
一、 __init__
__init__
簡化版代碼:
python def __init__(self, handlers=None, default_host="", transforms=None,
**settings):
if transforms is None:
self.transforms = []
if settings.get("compress_response") or settings.get("gzip"):
self.transforms.append(GZipContentEncoding)
else:
self.transforms = transforms
......
self.ui_modules = {'linkify': _linkify,
'xsrf_form_html': _xsrf_form_html,
'Template': TemplateModule,
}
self.ui_methods = {}
self._load_ui_modules(settings.get("ui_modules", {}))
self._load_ui_methods(settings.get("ui_methods", {}))
if self.settings.get("static_path"):
......
if handlers:
self.add_handlers(".*$", handlers)
if self.settings.get('debug'):
self.settings.setdefault('autoreload', True)
......
# Automatically reload modified modules
if self.settings.get('autoreload'):
from tornado import autoreload
autoreload.start()
參數
handlers
是一個list,list裡每個object是一個
URLSpec
的對象或tuple。tuple可以是二到四個element,分别是URI的正則、handler類、用于初始化
URLSpec
的kwargs、handler的name。
(下面add_handlers詳細說明)
參數
settings
是一個dict,所有settings的具體用法
- 初始化transforms(HTTP傳輸壓縮等,預設GZipContentEncoding 和 ChunkedTransferEncoding 。也可以自己實作,需要實作 transform_first_chunk 和 transform_chunk 接口,RequestHandler 中的 flush 調用,剖析RequestHandler時詳細介紹),UI子產品
- 通過settings的值來初始化靜态檔案處理Handler,包括:
- static_path
- static_url_prefix
- static_handler_class
- static_handler_args
- static_hash_cache
- 初始化其他settings
- 調用
方法添加handlers。add_handlers
- 加載自動重新加載子產品(當檢測到代碼被修改後重構啟動)
二、 add_handle
add_handle
python def add_handlers(self, host_pattern, host_handlers):
if not host_pattern.endswith("$"):
host_pattern += "$"
handlers = []
if self.handlers and self.handlers[-1][0].pattern == '.*$':
self.handlers.insert(-1, (re.compile(host_pattern), handlers))
else:
self.handlers.append((re.compile(host_pattern), handlers))
for spec in host_handlers:
if isinstance(spec, (tuple, list)):
assert len(spec) in (2, 3, 4)
spec = URLSpec(*spec)
handlers.append(spec)
if spec.name:
if spec.name in self.named_handlers:
app_log.warning(
"Multiple handlers named %s; replacing previous value",
spec.name)
self.named_handlers[spec.name] = spec
将host_pattern和handlers,組成tuple加到
self.handlers
的末尾但是在比對所有域名的tuple前。
由
spec = URLSpec(*spec)
易看出初始化Application的時候的第一個參數存的tuple是用來初始化URLSpec的是以參數順序應該和URLSpec要求的一樣(
def __init__(self, pattern, handler, kwargs=None, name=None)
)。
用過第四個參數name來構造反響代理,儲存在Application的named_handlers(dict)裡。
hello world裡調用了Application的
listen
和
tornado.ioloop.IOLoop.instance().start()
(以後會詳細介紹ioloop),來真正啟動。
三、 listen
listen
python def listen(self, port, address="", **kwargs):
from tornado.httpserver import HTTPServer
server = HTTPServer(self, **kwargs)
server.listen(port, address)
執行個體化一個HTTPServer,将application綁定上去。HTTPServer調用application的
start_request
來将application和connection綁定在一起初始化一個_RequestDispatcher的對象,由其來處理請求的路由,來利用
add_handler
建立的規則。
原文連接配接