• go转Python:我总是担心调用的函数会不会有异常 这是不是种病?
  • 发布于 2天前
  • 19 热度
    18 评论
之前写 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 给我的感受就是,想写好一个健壮的程序,有很大的心智负担,我总是要考虑我调用的函数会不会有异常。
用户评论
  • 浮生若梦
  • 两者设计思路不一样,不能直接套用!在传统的异常处理里面,不需要考虑这么多东西,避免心智负担。异常这种东西,如果处理不了,那就不要处理,就直接让它抛出,交给上一层,上一层决定是放弃,还是重试,又或者不处理,不行就直接 crash,例如打开文件时文件不存在,文件不存在不好处理,直接 crash 损失更小,避免错误执行。
  • 2025/6/25 12:08:00 [ 0 ] [ 0 ] 回复
  • 蓦然回首
  • 脚本语言最大优势就是随时改,不用全部编译,尤其是调参脚本,谁会 ratio 改个 0.01 重新编译一遍啊,所以没必要的情况下不必写 try...except 容错,直接让它报错还更清晰(直接就显示哪一行出错),try...except 更多是有两种方案时,此路不通换另一条,或者某些问题不重要,出错也可以 pass ,节省时间。

    初学的时候,确实对出错很敏感,但 python 写多几年就知道了,只要不是数据改动大,或者跑几小时的项目,报错不必紧张,及早发现比产出时报错好得多,不宜太早写 try,python 需要写容错的地方确实太多了,会的人知道 try...except 就是“掩饰”用的,产品真不适合给小白用户
  • 2025/6/25 12:06:00 [ 0 ] [ 0 ] 回复
  • 天长地久
  • 同感,所以每次想到那帮提案把 try cache 加到 go 里的人是不是脑子有什么大病。还有说“你可以截获不同的具体异常阿”,那么我怎么知道都有什么类型的异常呢?当前确实可以去源码里找,但是这和楼主说的“TMD 根本不知道这个函数会不会异常”是一个问题,可以说是心智负担+心智负担,相比之下明确返回 err 并在注释 doc 写上都可能有什么样的异常是最省心的。
  • 2025/6/25 12:05:00 [ 0 ] [ 0 ] 回复
  • 时间扯淡
  • 我看你不过是困在 go 里面还没出来罢了,说来说去你这不就可能存在 3 个异常吗?文件不存在,文件没法读取,json 解析异常,对应你 go 的逻辑,你这么写不就行了?
    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('...')

  • 2025/6/25 12:04:00 [ 0 ] [ 0 ] 回复
  • 旧城回眸
  • 相比于 Go, Python 确实存在意想不到的报错这种情况。健壮的 Python 代码来自于经验,老练的 Python 使用者熟知常用库和方法会出现什么问题,哪里需要处理异常,并将异常融入自己设计的控制流。所以 Python 写好并不容易,Go 的异常模式确实有其优势,虽然更多是被批评,但也看和谁比。
  • 2025/6/25 12:03:00 [ 0 ] [ 0 ] 回复
  • 入戏太深
  • 对 py 项目的糟糕印象来自某个几 k stars 的项目, 工程化处于能跑就行, 依赖管理就一个 requirements.txt requirements-dev.txt
    代码里类型乱传, 有时数组 有时非数组. 有时可以整数 有时可以小数. 遇到异常整个程序就挂了.
  • 2025/6/25 12:02:00 [ 0 ] [ 0 ] 回复
  • 都是戏子
  • python 一般都是运行脚本,异常会精确定位到行,所以不会有你说的 debug 问题。
    因此,python 操作上尽量不要 try except ,即便使用,在不能完全消化错误的时候也要打印原始异常调用栈。
  • 2025/6/25 12:01:00 [ 0 ] [ 0 ] 回复
  • 我们的回忆
  • 你看看错误处理代码,下面两种占多少
    1. 记录 error ,并且把 error return 给调用者
    2. 直接把 error return 给调用者
    很多时候我们不关心每个具体错误,只是在某个地方记录出错的调用栈和位置和一个简单的描述,此时 exception 就是更简单的选择。用 panic-revover 模拟 try-catch 的代码没少见吧?
  • 2025/6/25 11:59:00 [ 0 ] [ 0 ] 回复
  • 撕烂的回忆
  • 这俩语言都是用来快工出糙活的。不是说你考虑错误处理不对,而是语言设计者就不希望你这么写,最自然的方式就是 let it crash 。如果希望严谨处理,你应该看 Rust 之类的有强错误标记的语言,或者等等接下来的 Kotlin 2.4 。
  • 2025/6/25 11:56:00 [ 0 ] [ 0 ] 回复
  • 轻描淡写
  • 打印个 "打开文件失败" 就叫处理异常吗,你的 go 代码里前面都失败了还在往后走呢。一般这类错误本来就不用管,直接看程序打印的异常堆栈就知道那行出错了。大型项目一般都有全局异常处理,根据异常类型统一处理和返回,写的时候除非特殊情况要处理,一般也不需要太关注,最多就转成个自定义 exception 抛出去就好了。
  • 2025/6/25 9:20:00 [ 0 ] [ 0 ] 回复
  • 恍惚忆起
  • 我感觉 go 的写法挺好的,好几年前写前端的时候,也会把 trycatch 改造成 const [err, res] = xxx 这种写法,比 trycatch 嵌套好用多了
  • 2025/6/25 9:17:00 [ 0 ] [ 0 ] 回复
  • 繁华的年代
  • python 动态类型确实不适合写大项目,异常的话,如果数据格式确保百分百不会问题,就不需要处理,如果是 IO 函数,处理文件 IO 或者网络 IO ,统一 try,一般出现错误的基本都是这些操作
  • 2025/6/25 9:14:00 [ 0 ] [ 0 ] 回复