之前写 go ,go 调用函数的时候,有问题就是通过 返回值 有没有 err 来判断。心智负担很小,直接撸就行。一个简单的案例,打开文件,然后 json 解析。 go 版本是
func TestA(t *testing.T) {
fd, err := os.OpenFile("a.txt", os.O_RDWR, 0666)
if err != nil {
fmt.Println("打开文件失败", err)
}
defer fd.Close()
var data map[string]string
err = json.NewDecoder(fd).Decode(&data)
if err != nil {
fmt.Println("解析文件失败", err)
}
fmt.Println(data)
}
但是到 python 这边
f = open("a.json")
data = json.load(f)
f.close()
但是吧
如果文件不存在需要处理
文件存在,open() 执行异常了要处理
json.load() 会不会异常?我跳转源码看 josn.load()源码也没看到他会返回哪些异常信息。
所以我写出这种代码
try:
with open("a.json", "r") as f:
data = json.load(f)
except Exception as e:
print(e)
但是这样把多种异常合到一个 Exception 了,如果出现异常,你不知道是哪个函数调用出现的异常。所以就需要这样。
try:
with open("a.json", "r") as f:
try:
data = json.load(f)
except Exception as e:
print(e)
except Exception as e:
print(e)
然后我发现,最大的问题就是,我每次调用一个外部函数的时候,TMD 根本不知道这个函数会不会异常,总不能每个函数调用都用 try/except 处理一下?
try:
f1()
except Exception as e:
print(e)
try:
f2()
except Exception as e:
print(e)
try:
f3()
except Exception as e:
print(e)
写 python 给我的感受就是,想写好一个健壮的程序,有很大的心智负担,我总是要考虑我调用的函数会不会有异常。
初学的时候,确实对出错很敏感,但 python 写多几年就知道了,只要不是数据改动大,或者跑几小时的项目,报错不必紧张,及早发现比产出时报错好得多,不宜太早写 try,python 需要写容错的地方确实太多了,会的人知道 try...except 就是“掩饰”用的,产品真不适合给小白用户
或者你实在是要求细致到每一种异常,那你统一去 except 里面逐个处理不就行了
代码里类型乱传, 有时数组 有时非数组. 有时可以整数 有时可以小数. 遇到异常整个程序就挂了.
因此,python 操作上尽量不要 try except ,即便使用,在不能完全消化错误的时候也要打印原始异常调用栈。
1. 记录 error ,并且把 error return 给调用者
2. 直接把 error return 给调用者
很多时候我们不关心每个具体错误,只是在某个地方记录出错的调用栈和位置和一个简单的描述,此时 exception 就是更简单的选择。用 panic-revover 模拟 try-catch 的代码没少见吧?
try:
except A as e:
...
except B as e:
...