tornado.web包含web框架的大部分主要功能,Application是其中一个重要的类
Application类的作用是实现 URI 转发,将 Application 的实例传递给 httpserver ,当监听到请求时,把服务器传回来的请求进行转发,通过调用 __call__ ,处理请求。
Application源码:
- class Application(httputil.HTTPServerConnectionDelegate):
- """A collection of request handlers that make up a web application.
- Instances of this class are callable and can be passed directly to
- HTTPServer to serve the application::
- application = web.Application([
- (r"/", MainPageHandler),
- ])
- http_server = httpserver.HTTPServer(application)
- http_server.listen(8080)
- ioloop.IOLoop.instance().start()
- The constructor for this class takes in a list of `URLSpec` objects
- or (regexp, request_class) tuples. When we receive requests, we
- iterate over the list in order and instantiate an instance of the
- first request class whose regexp matches the request path.
- The request class can be specified as either a class object or a
- (fully-qualified) name.
- Each tuple can contain additional elements, which correspond to the
- arguments to the `URLSpec` constructor. (Prior to Tornado 3.2, this
- only tuples of two or three elements were allowed).
- A dictionary may be passed as the third element of the tuple,
- which will be used as keyword arguments to the handler's
- constructor and `~RequestHandler.initialize` method. This pattern
- is used for the `StaticFileHandler` in this example (note that a
- `StaticFileHandler` can be installed automatically with the
- static_path setting described below)::
- application = web.Application([
- (r"/static/(.*)", web.StaticFileHandler, {"path": "/var/www"}),
- ])
- We support virtual hosts with the `add_handlers` method, which takes in
- a host regular expression as the first argument::
- application.add_handlers(r"www\.myhost\.com", [
- (r"/article/([0-9]+)", ArticleHandler),
- ])
- You can serve static files by sending the ``static_path`` setting
- as a keyword argument. We will serve those files from the
- ``/static/`` URI (this is configurable with the
- ``static_url_prefix`` setting), and we will serve ``/favicon.ico``
- and ``/robots.txt`` from the same directory. A custom subclass of
- `StaticFileHandler` can be specified with the
- ``static_handler_class`` setting.
- """
- 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.handlers = []
- self.named_handlers = {}
- self.default_host = default_host
- self.settings = settings
- 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"):
- path = self.settings["static_path"]
- handlers = list(handlers or [])
- 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
- 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))
- if handlers:
- self.add_handlers(".*$", handlers)
- if self.settings.get('debug'): # 如果debug = True, 开启autoreload 和 serve_traceback功能(出错显示错误信息), 关闭compiled_template_cache和static_hash_cache<span style="font-family: Arial, Helvetica, sans-serif;">功能</span>
- 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)
- # Automatically reload modified modules
- if self.settings.get('autoreload'): # 服务能够自动reload新的代码
- from tornado import autoreload
- autoreload.start()
- def listen(self, port, address="", **kwargs):
- """Starts an HTTP server for this application on the given port.
- This is a convenience alias for creating an `.HTTPServer`
- object and calling its listen method. Keyword arguments not
- supported by `HTTPServer.listen <.TCPServer.listen>` are passed to the
- `.HTTPServer` constructor. For advanced uses
- (e.g. multi-process mode), do not use this method; create an
- `.HTTPServer` and call its
- `.TCPServer.bind`/`.TCPServer.start` methods directly.
- Note that after calling this method you still need to call
- ``IOLoop.instance().start()`` to start the server.
- 接受端口,地址,其它参数
- 建立http服务器并监听该端口
- """
- # import is here rather than top level because HTTPServer
- # is not importable on appengine
- from tornado.httpserver import HTTPServer
- server = HTTPServer(self, **kwargs)
- server.listen(port, address)
- def add_handlers(self, host_pattern, host_handlers):
- """Appends the given handlers to our handler list.
- Host patterns are processed sequentially in the order they were
- added. All matching patterns will be considered.
- """
- if not host_pattern.endswith("$"):
- host_pattern += "$"
- handlers = []
- # The handlers with the wildcard host_pattern are a special
- # case - they're added in the constructor but should have lower
- # precedence than the more-precise handlers added later.
- # If a wildcard handler group exists, it should always be last
- # in the list, so insert new groups just before it.
- 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
- def add_transform(self, transform_class):
- self.transforms.append(transform_class)
- def _get_host_handlers(self, request):
- host = request.host.lower().split(':')[0]
- matches = []
- for pattern, handlers in self.handlers:
- if pattern.match(host):
- matches.extend(handlers)
- # Look for default host if not behind load balancer (for debugging)
- if not matches and "X-Real-Ip" not in request.headers:
- for pattern, handlers in self.handlers:
- if pattern.match(self.default_host):
- matches.extend(handlers)
- return matches or None
- def _load_ui_methods(self, methods):
- if isinstance(methods, types.ModuleType):
- self._load_ui_methods(dict((n, getattr(methods, n))
- for n in dir(methods)))
- elif isinstance(methods, list):
- for m in methods:
- self._load_ui_methods(m)
- else:
- for name, fn in methods.items():
- if not name.startswith("_") and hasattr(fn, "__call__") \
- and name[0].lower() == name[0]:
- self.ui_methods[name] = fn
- def _load_ui_modules(self, modules):
- if isinstance(modules, types.ModuleType):
- self._load_ui_modules(dict((n, getattr(modules, n))
- for n in dir(modules)))
- elif isinstance(modules, list):
- for m in modules:
- self._load_ui_modules(m)
- else:
- assert isinstance(modules, dict)
- for name, cls in modules.items():
- try:
- if issubclass(cls, UIModule):
- self.ui_modules[name] = cls
- except TypeError:
- pass
- def start_request(self, connection):
- # Modern HTTPServer interface
- return _RequestDispatcher(self, connection)
- def __call__(self, request):
- # Legacy HTTPServer interface
- dispatcher = _RequestDispatcher(self, None)
- dispatcher.set_request(request)
- return dispatcher.execute()
- def reverse_url(self, name, *args):
- """Returns a URL path for handler named ``name``
- The handler must be added to the application as a named `URLSpec`.
- Args will be substituted for capturing groups in the `URLSpec` regex.
- They will be converted to strings if necessary, encoded as utf8,
- and url-escaped.
- 根据name返回匹配的url路径
- """
- if name in self.named_handlers:
- return self.named_handlers[name].reverse(*args)
- raise KeyError("%s not found in named urls" % name)
- def log_request(self, handler):
- """Writes a completed HTTP request to the logs.
- By default writes to the python root logger. To change
- this behavior either subclass Application and override this method,
- or pass a function in the application settings dictionary as
- ``log_function``.
- 把HTTP请求写进日志
- http状态码小于400的为正常
- 大于等于400小于500<span style="font-family: Arial, Helvetica, sans-serif;">为</span><span style="font-family: Arial, Helvetica, sans-serif;">请求错误</span>
- 大于500是服务器错误
- """
- if "log_function" in self.settings:
- self.settings["log_function"](handler)
- return
- if handler.get_status() < 400:
- log_method = access_log.info
- elif handler.get_status() < 500:
- log_method = access_log.warning
- else:
- log_method = access_log.error
- request_time = 1000.0 * handler.request.request_time()
- log_method("%d %s %.2fms", handler.get_status(),
- handler._request_summary(), request_time)
构造函数
__init__(self,handlers=None,default_host="",transforms=None,**settings)
它接受handlers (包含匹配规则和requesthandler的元组),default_host(默认主机),transforms(输出做分块和压缩的转换)和setting(包含配置的字典)。
建立主机的路径路由规则
方法
listen(self, port, address="", **kwargs) 建立http服务器并监听该端口
add_handlers(self, host_pattern, host_handlers)向handler列表中添加handler。host_pattern依次按照它们的添加顺序进行处理,添加主机的路径路由规则
add_transform(self, transform_class)向self.transforms增加transform_class,对输出做分块和压缩的转换
_get_host_handlers(self, request)寻找属于这个request的handlers
_load_ui_methods(self, methods)在self.ui_methods中添加方法
_load_ui_modules(self, modules)在self.ui_modules中添加方法
reverse_url(self, name, *args)使用name返回匹配的url路径
__call__(self, request) 在服务器接受新连接时被调用 接受HttpRequest对象 根据 httprequest 调用execute 方法
start_request(self, connection)作用同__call__
log_request(self, handler)把HTTP请求写进日志。
debug=True 时代码动态自动编译的原理
Application 对象实例化时,给出“debug=True”参数的话,开启autoreload 和 serve_traceback功能(出错显示错误信息) , 关闭compiled_template_cache和static_hash_cache功能
autoreload:改变源代码的时候,服务器进程将能够自动reload新的代码并重启。
serve_traceback:如果开启,在出错的时候就不是返回默认的错误页面,取而代之的是显示python的traceback,利用这个我们可以看到在什么地方出现了错误,可以进行方便的调试。
compiled_template_cache:编译模板缓存,如果关闭,在刷新时服务器的模板都会重新加载。
static_hash_cache:静态哈希缓存,如果关闭,在刷新时有static_url()的地方都会重新载入需要读取的static下的文件,而不是用已经缓存了的文件。
本文介绍了Tornado Web框架的核心组件Application的功能与使用方法,包括如何设置路径规则、启动服务器、处理HTTP请求等。
597

被折叠的 条评论
为什么被折叠?



