用 try...except...提高代码的稳定性,是否是好习惯?

2020-05-29 19:25:08 +08:00
 Leon6868

把每个可能出错的东西都套上 try...except,这样有什么坏处吗?
比如,是否会影响代码的执行效率?

8557 次点击
所在节点    Python
48 条回复
agagega
2020-05-29 23:01:23 +08:00
断言、异常和错误码(或者 Maybe 类型)是三种用途:
1. 断言是「绝对不应该出现的错误」,如果出现了,表明是你的代码有 bug 。换言之,断言的作用是辅助 debug
2. 异常是「不太可能出现,出现了我也不太能继续处理」的问题,比如内存不够了,网络断了
3. 错误码是「不希望它出现,但出现了我也应该要处理」的问题,比如错误的用户输入

Java 里面似乎会用异常来负责一些错误码的功能,Python 听说甚至会用异常来代替部分控制流。但总体的思路就是这样。
fancy2020
2020-05-29 23:06:05 +08:00
我觉得用 try catch 的最大前提是想清楚,这个错误应该在系统的哪一个层级来处理~
上边有人说到 let it crash 的思想,我觉得这是因为在 Erlang 中每一个轻量级进程崩了并不影响整个系统的运行(其实相当于是 Erlang 虚拟机帮你有个兜底的 catch),像其他语言如果任由你的代码 crash 那肯定是不行的。
liyongqiang1995
2020-05-29 23:12:53 +08:00
个人理解,可能出错的地方要 try, 如果是预料中可能发生的错误且不影响继续运行就不 raise,否则打印一定上下文再 raise
UnknownR
2020-05-29 23:27:18 +08:00
用 try catch,是为了规避异常抛出而打断持续进程,有些地方的 exception 如果对现有进程没有影响,那你可以直接 catch 然后作为一个记录。

如果你需要进程从头到尾按你的需求执行,不写 catch 块让他自然抛出才是建议的做法,但是比如你要执行一个循环查询,有异常只需记录你又不能枚举所有异常类型,那可以直接 catch 并存储。
ZRS
2020-05-29 23:43:32 +08:00
只要别 except Exception 就行。。
Jirajine
2020-05-29 23:56:17 +08:00
@GeruzoniAnsasu 你这样说确实有道理,让我想到所谓大部分错误都是暂时的,重启能解决 90%的问题。elixir 文档里说的遇到错误就快速退出然后重启,让系统回到一个已知的正确的状态,从而使整个系统具有很高的容错性。

但任何事情都有 trade off,抛异常直接跳出来确实比插一根管子层层返回错误要优雅,但也太过狂野。
当进行一个可能失败的操作时,使用异常就得包到一层 try 里面,错误跳到 catch 里处理,如果我想失败重试,整个控制流就会非常混乱。
这种情况直接返回一个包含了成功时的结果或失败时的原因的结构则要清晰很多,无论是直接裸返回再手写 iferr 还是包到 Result 里面用 pattern match,错误处理包含在常规控制流中。
日常使用时这种情况占绝大多数,所以较新的语言开始用直接返回替代异常控制流作为绝大多数情况下的错误处理方式,当然少部分时候有时也确实需要回滚,所以也有提供类似异常的 panic recover 机制,我觉得这是正确的发展方向。
hellov22ex
2020-05-30 00:08:37 +08:00
少用这个东西,除非是你自己很熟悉的代码,不然你不知道会导致软件系统产生什么奇怪的状态。
love
2020-05-30 00:33:22 +08:00
骚年,你这做法完全和各种编程实践文章背道而驰了,应该只处理预期的必要异常,其他都要往上穿,是否要在顶层崩溃掉程序看实际程序业务
sazima
2020-05-30 00:42:06 +08:00
try:
xxx
except Exception:
logger.warn('......')
raise
ArtIsPatrick
2020-05-30 00:49:26 +08:00
当然不是,大部分情况在最外层用装饰器( Python )或者切面( Java )处理异常就行了,里面根据情况看是否需要抛出特定的异常,否则不必再写 try catch 。
zhuangzhuang1988
2020-05-30 01:04:09 +08:00
没有必然联系.
maomaomao001
2020-05-30 03:21:23 +08:00
肯定不能到处 try catch 啊 , 程序(函数 ,模块) 入口部分检查好, 中间纯逻辑部分你在检查 try catch 肯定是很严重的设计错误
CismonX
2020-05-30 03:55:07 +08:00
try:
# ...
except Exception:
pass

公司项目里面都是这样的代码。。
lizytalk
2020-05-30 07:02:45 +08:00
@Leon6868 如果不把具体错误打出来当发生故障的时候你不知道故障在哪
crclz
2020-05-30 08:03:10 +08:00
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/exception-throwing
❌ DO NOT return error codes.
✔️ DO report execution failures by throwing exceptions.

❌ DO NOT use exceptions for the normal flow of control, if possible.
For example, you can provide a way to check preconditions before calling a member so users can write code that does not throw exceptions.

The member used to check preconditions of another member is often referred to as a [tester] , and the member that actually does the work is called a [doer] .

Tester-Doer Pattern https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/exceptions-and-performance
xingheng
2020-05-30 08:20:12 +08:00
@GeruzoniAnsasu 在业务层“回滚调用栈”应该是手动 raise custom eexception 吧,这样理解应该没问题吧
weyou
2020-05-30 09:13:16 +08:00
@cozof @superrichman 最简单就是 sys.excepthook
mjikop1231
2020-05-30 09:21:43 +08:00
然后跑去 GO,emmmm
xuanbg
2020-05-30 09:22:49 +08:00
尽量少用,除非是可以预见且应该处理的异常,譬如网络请求超时这种。
janxin
2020-05-30 10:18:29 +08:00
try/catch 是需要你按照一定规律处理错误的,部分错误也是必须要向上抛出的。

具体是你可能需要根据不同错误进行不同处理

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

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

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

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

© 2021 V2EX