Python技术迷

如何处理Python中的异常?

哎,昨天晚上在公司加班到十一点多,结果最后上线前临时又来一堆bug,我人都麻了,正好说到这个话题,Python异常怎么处理,真是最近项目里最头疼的事。我们组那个小李,上周写了个定时任务,结果有个地方没try...except,直接把整个任务给挂死了,还好是测试环境,不然就炸锅了。

其实说白了,Python的异常处理,真没啥玄学,就是你代码写多了自然会有感觉。不过也有不少坑,尤其是刚入门的时候容易一股脑except Exception,啥都吞了,后面调试全靠蒙,血泪教训我跟你说。

先说最基本的用法,你写个最简单的try...except,这个用得最多了,比如说:

try:
    result = 10 / 0
except ZeroDivisionError as e:
    print("除零啦,快看看出啥问题了", e)

你们平时是不是都这么写?其实挺够用的,除非你非要搞点骚操作,比如想无脑兜底——我劝你还是慎用:

try:
    do_something()
except Exception as e:
    print("卧槽,出错了", e)

但这种写法我现在已经不用了,尤其是线上服务,这玩意会把一些你意想不到的bug给吞掉,比如内存爆了啊、进程kill信号啊,根本捕获不到,最后日志还贼难看。

对了,还有个很容易被忽略的点,就是try...except还可以加else和finally。我有时候处理文件啥的,经常要用:

try:
    f = open('data.txt', 'r')
except FileNotFoundError:
    print("文件找不到,可能是路径写错了")
else:
    print(f.read())
    f.close()
finally:
    print("这个finally,不管你上面出没出错,都会执行,比如你要关资源啊啥的")

其实我之前还踩过个坑,就是finally里面又抛异常,前面的异常就直接被覆盖了,最后一脸懵逼查不到主因。所以finally里头还是别乱搞。

你们是不是也经常遇到写except的时候一激动把所有异常全兜了?说真的,能细分就细分,比如你处理网络请求的异常,可以专门捕获requests.exceptions.RequestException,别什么Exception一把梭,后面你自己也搞不清楚到底哪出错了。我们组有个小伙前两天写的日志,全是except Exception,然后print("error!"),啥错都一个提示,哈哈哈,老大直接崩溃。

还有一个特别重要的事,尤其是写库或者做平台接口的时候,绝对别用 bare except,就是那个except:啥都不写的,我之前就吃过亏,那个KeyboardInterrupt、SystemExit都被抓进去了,服务怎么都停不下来,最后只能kill -9。

如果有多种异常需要处理,try...except还能这样写:

try:
    something()
except (TypeError, ValueError) as e:
    print("类型或者数值错了", e)

这个其实挺常用的,尤其是写一些转换逻辑或者API调用,经常碰到类型和数值的错,合起来处理更舒服。

另外补一句,你们用logging没?print调试只能救急,线上服务全靠logging:

import logging

try:
    something()
except Exception as e:
    logging.exception("代码炸了")

这样日志里还能看到traceback,方便后面定位问题,尤其是夜里睡迷糊被call起来的时候,省事儿多了。

哦对,写完catch还得记得抛,有些场景不能全兜底,得继续往上抛,不然上一层啥都不知道,比如这样:

try:
    foo()
except ValueError as e:
    print("有问题,抛出去")
raise

说了这么多,其实你就记住,能精确就精确,能补日志就别直接吞掉,finally别乱抛,bare except慎用,logging得加上,就够你日常用了。对了,想偷懒全用Exception兜的,真的别,老板追日志的时候你会怀疑人生。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领