go 转 Python 的心智负担增加

92 天前
 yujianwjj

之前写 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()

但是吧

  1. 如果文件不存在需要处理
  2. 文件存在,open() 执行异常了要处理
  3. 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 给我的感受就是,想写好一个健壮的程序,有很大的心智负担,我总是要考虑我调用的函数会不会有异常。

9740 次点击
所在节点    Python
99 条回复
cloudzhou
92 天前
这就是经典的 error vs exception 争议
Sawyerhou
92 天前
go 的异常处理比较特殊,除非你不想学其他语言,否则走出舒适圈是不可避免的。
Lockroach
92 天前
fd, err: xxx
if err != nil
这样的行为,和 try: ... except Exception: ... 似乎也没什么区别,都是捕获一个笼统错误
如果要捕获精确错误,应该有精细化的 Exception 实例
iyaozhen
92 天前
大家不要纠结于楼主的 print 嘛 只是示例

这个其实就是经典的错误处理之争,要是有定论,go 早就采用了

其实大家写 python 基本也不处理异常,触发非常特殊的地方。不然就是最外层一个 try catch ,至于错误类型,会打印出来的,也有堆栈
go 也有 go 的问题,除了繁琐(这可能优点),另外就是 err 往上抛,最外层不知道哪里错了(当然有各种解决办法)
uds9u32br
92 天前
同感,陆陆续续几年写了点 python ,写的挺烦的。
zoharSoul
92 天前
肯定在最外层统一处理啊
go 那种一行一判断麻烦的要死
sagaxu
92 天前
你看看错误处理代码,下面两种占多少
1. 记录 error ,并且把 error return 给调用者
2. 直接把 error return 给调用者

很多时候我们不关心每个具体错误,只是在某个地方记录出错的调用栈和位置和一个简单的描述,此时 exception 就是更简单的选择。用 panic-revover 模拟 try-catch 的代码没少见吧?
ksedz
92 天前
python 一般都是运行脚本,异常会精确定位到行,所以不会有你说的 debug 问题。
因此,python 操作上尽量不要 try except ,即便使用,在不能完全消化错误的时候也要打印原始异常调用栈。
ajunno
92 天前
python 有个用装饰器代替 try...catch...代码块的库 merry https://merry-py.readthedocs.io/en/latest/quickstart.html#getting-started
jqtmviyu
92 天前
对 py 项目的糟糕印象来自某个几 k stars 的项目, 工程化处于能跑就行, 依赖管理就一个 requirements.txt requirements-dev.txt
代码里类型乱传, 有时数组 有时非数组. 有时可以整数 有时可以小数. 遇到异常整个程序就挂了.
coderluan
92 天前
都没说到重点吧,python 的 with 本身就是解决文件异常的问题,也就是 with open 就不用加 try 了,也就是这个代码在 json.load 加 try 就行了。

至于后面有多个函数的情况,比如 f1 ,f2 ,那么在最开始的时候加一个 try ,想知道的具体哪个错了,应该在 except 的时候输出下 traceback 。
tairan2006
92 天前
fast fail

外围加一个大的 try...except 就行
Rorysky
92 天前
just let it fail
coderluan
92 天前
except Exception as e:
print(e)
traceback.print_exc()
arischow
92 天前
https://docs.python.org/3.12/library/json.html#json.load

> If the data being deserialized is not a valid JSON document, a JSONDecodeError will be raised.
shinession
92 天前
只要 try 一次就行了, 异常类型可以判断, 也可用 traceback 解析, OP 这是没入门就来找茬
DonaldVVV
92 天前
try
exception exception as e:
print(f'{e!r}')

一个 print ,会把错误堆栈都打印出来,不管什么错误。跟 go 那个就差不多了
Donahue
92 天前
为什么要处理异常,有问题了直接看报错 debug(笑)
python 感觉不适合用来写太严谨的代码,会很麻烦
deplives
92 天前
菜就多练 就举的这个例子的代码 都不想吐槽
用了 with 还在外面包 try 那你猜 with 是干啥的
还有 json 有一个方法教叫 loads 可以了解一下,下次真要喷 找个合理的例子
Gilfoyle26
92 天前
python 还需要异常处理。。。。。我都是写脚本,用完就弃。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1140619

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX