首页 注册 登录
V2EX = way to explore V2EX 是一个关于分享和探索的地方
现在注册 已注册用户请 登录
Tornado Documentation http://www.v2ex.com/tornado/ Tornado on GitHub https://github.com/facebook/tornado/ Tornado Gists http://tornadogists.org/
V2EX Tornado

问一个关于 tornado 异常处理的新手问题

mgna17 · 2016 年 6 月 5 日 · 14032 次点击
这是一个创建于 3506 天前的主题,其中的信息可能已经有所发展或是发生改变。

刚开始学 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 !')
7 条回复 2016年08月13日 00:36:06 +08:00
momo1999
1
momo1999 2016 年 6 月 5 日
tornado.web.RequestHandler.write_error = write_error

我是这样写的
lianghui
2
lianghui 2016 年 6 月 5 日
```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).

```
mgna17
3
mgna17
OP
2016 年 6 月 5 日 via Android
@shuax 这样写结果上和我的继承覆盖写法没差别吧 😓
mgna17
4
mgna17
OP
2016 年 6 月 5 日 via Android
@lianghui 谢谢你的回答,这是一个优雅的解决方案,但是,实际上我想知道的是:为什么我写的是错的
lianghui
5
lianghui 2016 年 6 月 5 日 ❤️ 2
@mgna17 因为 RequestDispatcher 在没有找到 handler 默认设置将 handler 为 ErrorHandler,如果指定了 default_handler_class ,就使用 default_handler_class 。

ErrorHandler 继承了 RequestHandler , 所以 hook RequestHandler.write_error 有效。 详细看 tornado.web._RequestDispatcher route 处理实现
mgna17
6
mgna17
OP
2016 年 6 月 5 日
@lianghui 非常感谢,我的问题解决了
lenbias34
7
lenbias34 2016 年 8 月 13 日
说白了 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 !错误
关于 · 帮助文档 · 自助推广系统 · 博客 · API · FAQ · Solana · 2650 人在线 最高记录 6679 · Select Language 创意工作者们的社区 World is powered by solitude VERSION: 3.9.8.5 · 27ms · UTC 11:43 · PVG 19:43 · LAX 03:43 · JFK 06:43
♥ Do have faith in what you're doing.

AltStyle によって変換されたページ (->オリジナル) /