之前写 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 就是“掩饰”用的,产品真不适合给小白用户
import json, os filename = 'a.txt' if not os.path.exists(filename): raise Exception('文件不存在') try: with open(filename) as f: json.load(f) except Exception as e: raise Exception(f'解析文件失败 {type(e)}')或者你实在是要求细致到每一种异常,那你统一去 except 里面逐个处理不就行了import json, os filename = 'b.txt' try: with open(filename) as f: json.load(f) except Exception as e: if isinstance(e, FileNotFoundError): raise Exception('文件不存在') elif isinstance(e, PermissionError): raise Exception('...') elif isinstance(e, json.decoder.JSONDecodeError): raise Exception('...') else: raise Exception('...')代码里类型乱传, 有时数组 有时非数组. 有时可以整数 有时可以小数. 遇到异常整个程序就挂了.
因此,python 操作上尽量不要 try except ,即便使用,在不能完全消化错误的时候也要打印原始异常调用栈。
1. 记录 error ,并且把 error return 给调用者
2. 直接把 error return 给调用者
很多时候我们不关心每个具体错误,只是在某个地方记录出错的调用栈和位置和一个简单的描述,此时 exception 就是更简单的选择。用 panic-revover 模拟 try-catch 的代码没少见吧?
try:
except A as e:
...
except B as e:
...