go 转 Python 的心智负担增加

9 天前
 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 给我的感受就是,想写好一个健壮的程序,有很大的心智负担,我总是要考虑我调用的函数会不会有异常。

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

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

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

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

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

外围加一个大的 try...except 就行
Rorysky
9 天前
just let it fail
coderluan
9 天前
except Exception as e:
print(e)
traceback.print_exc()
arischow
9 天前
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
9 天前
只要 try 一次就行了, 异常类型可以判断, 也可用 traceback 解析, OP 这是没入门就来找茬
DonaldVVV
9 天前
try
exception exception as e:
print(f'{e!r}')

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

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

https://ex.noerr.eu.org/t/1140619

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

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

© 2021 V2EX