初识tornado
经典的hello world 案例:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
application = tornado.web.Application([
(r"/index", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
程序执行流程:
1、创建Application 对象,把正则表达式和类名MainHandler传入构造函数,即: tornado.web.Application(...)
2、执行Application 对象的 listen(...) 方法,即: application.listen(8888)
3、执行IOLoop类的类的 start() 方法,即:tornado.ioloop.IOLoop.instance().start()
程序实质:创建一个socket 监听8888端口,当请求到来时,根据请求的url和请求方式(get,post,put)来指定相应的类中的方法来处理本次请求。
在浏览器上访问:http://127.0.0.1:8888/index,则服务器给浏览器就会返回 Hello,world ,否则返回 404: Not Found(tornado内部定义的值), 即完成一次http请求和响应。
由上述分析,我们将整个Web框架分为两大部分:
-
待请求阶段(程序启动阶段),即:创建服务端socket并监听端口
-
处理请求阶段,即:当有客户端连接时,接受请求,并根据请求的不同做出相应的相应
待请求阶段(程序启动阶段)
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
application = tornado.web.Application([ ## <======= 1
(r"/index", MainHandler),
])
if __name__ == "__main__":
application.listen(8888) ## <======== 2
tornado.ioloop.IOLoop.instance().start() ## <======== 3
1. application = tornado.web.Application([(xxx,xxx)])
def __init__(self, handlers=None, default_host="", transforms=None, **settings): # 设置响应的编码和返回方式,对应的http相应头:Content-Encoding和Transfer-Encoding # Content-Encoding:gzip 表示对数据进行压缩,然后再返回给用户,从而减少流量的传输。 # Transfer-Encoding:chunck 表示数据的传送方式通过一块一块的传输。 if transforms is None: self.transforms = [] if settings.get("compress_response") or settings.get("gzip"): self.transforms.append(GZipContentEncoding) else: self.transforms = transforms # 将参数赋值为类的变量 self.handlers = [] self.named_handlers = {} self.default_host = default_host self.settings = settings # ui_modules和ui_methods用于在模版语言中扩展自定义输出 # 这里将tornado内置的ui_modules和ui_methods添加到类的成员变量self.ui_modules和self.ui_methods中 self.ui_modules = {'linkify': _linkify, 'xsrf_form_html': _xsrf_form_html, 'Template': TemplateModule, } self.ui_methods = {} # 获取获取用户自定义的ui_modules和ui_methods,并将他们添加到之前创建的成员变量self.ui_modules和self.ui_methods中 self._load_ui_modules(settings.get("ui_modules", {})) self._load_ui_methods(settings.get("ui_methods", {})) # 设置静态文件路径,设置方式则是通过正则表达式匹配url,让StaticFileHandler来处理匹配的url if self.settings.get("static_path"): # 从settings中读取key为static_path的值,用于设置静态文件路径 path = self.settings["static_path"] # 获取参数中传入的handlers,如果空则设置为空列表 handlers = list(handlers or []) # 静态文件前缀,默认是/static/ static_url_prefix = settings.get("static_url_prefix", "/static/") static_handler_class = settings.get("static_handler_class", StaticFileHandler) static_handler_args = settings.get("static_handler_args", {}) static_handler_args['path'] = path # 在参数中传入的handlers前再添加三个映射: # 【/static/.*】 --> StaticFileHandler # 【/(favicon\.ico)】 --> StaticFileHandler # 【/(robots\.txt)】 --> StaticFileHandler for pattern in [re.escape(static_url_prefix) + r"(.*)", r"/(favicon\.ico)", r"/(robots\.txt)"]: handlers.insert(0, (pattern, static_handler_class, static_handler_args)) # 执行本类的Application的add_handlers方法 # 此时,handlers是一个列表,其中的每个元素都是一个对应关系,即:url正则表达式和处理匹配该正则的url的Handler if handlers: self.add_handlers(".*$", handlers) #<================== # Automatically reload modified modules # 如果settings中设置了 debug 模式,那么就使用自动加载重启 if self.settings.get('debug'): self.settings.setdefault('autoreload', True) self.settings.setdefault('compiled_template_cache', False) self.settings.setdefault('static_hash_cache', False) self.settings.setdefault('serve_traceback', True) if self.settings.get('autoreload'): from tornado import autoreload autoreload.start()