前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Python第三方库系列] - Better Exceptions

[Python第三方库系列] - Better Exceptions

作者头像
the5fire
发布2019-03-01 14:05:04
1.5K0
发布2019-03-01 14:05:04
举报

[Python第三方库系列] - Better Exceptions

Better Exceptions是最近一期的Python Weekly 和Pycoders Weekly上都推荐的一个库,用处是展示更友好的异常信息。

无论在什么语言里遇到异常是很正常的,遇到线上异常也是常有的。本地异常的话通过pdb调试/print输出关键信息是可行的,但是对于线上异常的话,只能从日志里查看,但日志里的信息可能只是提示你:ValueError: need more than 3 values to unpack 或者是 KeyError: 'a',遇到这种问题,一般的做法是本地启动项目,尝试重现,这样你才能知道上下文是什么。但,往往很难复现,因为从日志里你看不到用户的输入是什么?如果你没有手动捕获异常,并把造成异常的数据写入log。(当然,最好的做法其实是使用Sentry)

上面的错误可以简化为这种形式:

代码语言:javascript
复制
# coding:utf-8
request = "test test test"  # 从request中获取到数据
a, b, c, d = request.split()  # 处理数据

# 运行后:
Traceback (most recent call last):
  File "exc.py", line 8, in <module>
      a, b, c, d = request.split()
ValueError: need more than 3 values to unpack

或者这种

代码语言:javascript
复制
# coding:utf-8
# 前端ajax传过来数据,后端处理
request_dict = {}
user_name = request_dict['user_name']

# 运行后:
Traceback (most recent call last):
  File "exc.py", line 5, in <module>
      user_name = request_dict['user_name']
KeyError: 'user_name'

后一种情况一个简单的场景就是,按照之前的逻辑,代码没问题,但是上线后,一直会报这个错误,为啥呢?谁也搞不清楚,只能去看用户到底发了什么数据,怎么看呢。把用户端发过来的数据打印出来?在生产环境这么做吗?(当然,最好的方法还是使用Sentry)

好了,这就是Better Exceptions出现的场景了。同样是上面的代码,增加 import better_exceptions之后就是这样:

代码语言:javascript
复制
# coding:utf-8
import better_exceptions

request = "test test test"  # 从request中获取到数据
a, b, c, d = request.split()  # 处理数据

# 运行后:
Traceback (most recent call last):
  File "exc.py", line 8, in <module>
      a, b, c, d = request.split()
                   └ 'test test test'    # 增加了内容
ValueError: need more than 3 values to unpack

或者这种

代码语言:javascript
复制
# coding:utf-8
import better_exceptions

# 前端ajax传过来数据,后端处理
request_dict = {}
user_name = request_dict['user_name']

# 运行后:
Traceback (most recent call last):
  File "exc.py", line 5, in <module>
      user_name = request_dict['user_name']
                  └ {}
KeyError: 'user_name'

Better Exceptions是怎么做到的呢

从上面的应用场景描述,以及最终呈现的结果来看,似乎是有用的。但是,对于Django和Tornado这样的Web框架,没啥用。为什么呢?

来看Better Exceptions的实现:

代码语言:javascript
复制
better_exceptions/__init__.py  最后几行代码

def excepthook(exc, value, tb):
    formatted, colored_source = format_traceback(tb)

    if not str(value) and exc is AssertionError:
        value.args = (colored_source,)
    title = traceback.format_exception_only(exc, value)

    full_trace = u'Traceback (most recent call last):\n{}{}\n'.format(formatted, title[0].strip())
    write_stream(full_trace)


sys.excepthook = excepthook  # 关键是这个

主要是用了sys模块的excepthook方法,这个方法的描述如下:

ref: https://docs.python.org/2/library/sys.html#sys.excepthook

This function prints out a given traceback and exception to sys.stderr. When an exception is raised and uncaught, the interpreter calls sys.excepthook with three arguments, the exception class, exception instance, and a traceback object. In an interactive session this happens just before control is returned to the prompt; in a Python program this happens just before the program exits. The handling of such top-level exceptions can be customized by assigning another three-argument function to sys.excepthook.

大概意思就是,如果系统抛出一个未捕获的异常,那么解释器就会调用sys.excepthook方法,同时传递三个参数:异常类(ValueError或者KeyError之类的),异常实例,和traceback对象。

这意味着,你可以通过重写这个方法来处理系统未捕获的异常处理。但,在框架中(我只看了Django代码,测试了Tornado)会自己处理异常,所以这种hook的方式不会被触发。

看到这里,可能会觉得,那这玩意有啥用呢?我能想到的场景是你自己写的爬虫,定时执行可以用的上,另外介绍这个库的另一个作用就是可以用来学习下Python中的几个模块,比如sys.excepthook, inspect, ast, TraceBack等模块的使用。

另外我上面也提到了两次Sentry,通过这个也可以看下,Sentry的Python客户端(Raven-Python)是怎么处理异常的。

这个库的安装直接pip就行:

代码语言:javascript
复制
pip install better-exceptions
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-03-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • [Python第三方库系列] - Better Exceptions
    • Better Exceptions是怎么做到的呢
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档