刚开始学 tornado ,它的异常处理机制有点弄不明白。
写了一个测试用的小脚本,期望遇到 404 的时候能够触发我自己声明的 write_error 函数,然而 write_error 并没有生效,输出的是 tornado 默认的 404 页面。
代码如下:
#!/bin/env python3.5
#coding:utf-8
import os
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options
define("port", default=8000, help="端口", type=int)
class BaseHandler(tornado.web.RequestHandler):
def write_error(self, stat, **kw):
self.write('Func write_error !')
class IndexHandler(BaseHandler):
def get(self):
self.write('hello')
handlers = [
(r'/index', IndexHandler),
]
settings = {
'template_path': os.path.join(os.path.dirname(__file__), "templates"),
'static_path': os.path.join(os.path.dirname(__file__), 'static'),
}
if __name__ == '__main__':
tornado.options.parse_command_line()
app = tornado.web.Application(handlers=handlers, **settings)
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
print(options.port)
tornado.ioloop.IOLoop.instance().start()
然后去 google 了一下,把 BaseHandler 成了这样,但是 404 的时候还是返回了默认的 404 页面:
class BaseHandler(tornado.web.RequestHandler):
def _handle_request_exception(self, e):
self.write_error(404)
def send_error(self, stat, **kw):
self.write_error(404)
def write_error(self, stat, **kw):
self.write('Func write_error !')
1
shuax 2016-06-05 18:22:32 +08:00
tornado.web.RequestHandler.write_error = write_error
我是这样写的 |
2
lianghui 2016-06-05 18:26:44 +08:00
```python
class NotFondHandler(BaseHandler): def get(self): self.write("This page ``{}``is not Found".format(self.request.path)) settings = { 'template_path': os.path.join(os.path.dirname(__file__), "templates"), 'static_path': os.path.join(os.path.dirname(__file__), 'static'), 'default_handler_class': NotFondHandler } default_handler_class and default_handler_args: This handler will be used if no other match is found; use this to implement custom 404 pages (new in Tornado 3.2). ``` |
4
mgna17 OP @lianghui 谢谢你的回答,这是一个优雅的解决方案,但是,实际上我想知道的是:为什么我写的是错的
|
5
lianghui 2016-06-05 19:01:34 +08:00 2
@mgna17 因为 RequestDispatcher 在没有找到 handler 默认设置将 handler 为 ErrorHandler,如果指定了 default_handler_class ,就使用 default_handler_class 。
ErrorHandler 继承了 RequestHandler , 所以 hook RequestHandler.write_error 有效。 详细看 tornado.web._RequestDispatcher route 处理实现 |
7
lenbias34 2016-08-13 00:36:06 +08:00
说白了 404 错误就是路由不匹配,
我们看 tornado 源码文件 web.py 中有 Application 类中的__call__方法中有: if not handler: handler = ErrorHandler(self, request, status_code=404) 也就是所有错误的路由( 404 )将统一由 ErrorHandler 来处理, 再看看 ErrorHandler 的源码定义: class ErrorHandler(RequestHandler): """Generates an error response with status_code for all requests.""" def initialize(self, status_code): self.set_status(status_code) def prepare(self): raise HTTPError(self._status_code) 可以看到 ErrorHandler 继承自 RequestHandler 而并非你自定义的 BaseHandler 类 所以即使你在 BaseHandler 中定义了 write_error 方法, ErrorHandler 中也不会有 write_error 的处理逻辑 PS :自定义的 write_error 逻辑将在请求路由存在, 但请求方法错误时被调用 比如,就拿你的代码来说: 如果你向 '/' 发出 POST 请求( curl -X POST http://localhost:8000/ ),就会返回 Func write_error !错误 |