后端接口是否用 try/except 好?还是不用好?

2018-10-29 14:06:19 +08:00
 zhangqilin

最近在看后台日志,一堆 try/except 后打印出的错误信息 但有这么一堆错误信息还是排查不出问题 我自己维护的项目中 try/except 很少,因为我觉得运用大量的 try 只是掩盖了问题,而不是去解决问题

而实际上我在维护别人项目的时候,比如一个接口的代码为:

  1. 获取参数
  2. 业务逻辑(一大块 try/except,出错了就返回 fail )
  3. 返回 ok/fail

这样在服务器日志里看到有打印出来的错误信息,很不爽,想去解决 但又找不到问题出在哪儿,因为报的也不多 可能是强迫症吧

因为这是我第一个公司,所以想问一下 V2EX 的同志们

究竟是大片的 try/except 好?还是几乎不写 try/except 好

或者说

try/except 究竟应该在哪些场合应用?

2798 次点击
所在节点    程序员
15 条回复
cy97cool
2018-10-29 14:31:08 +08:00
赶紧用 sentry

只有异常是期待中的 才需要用 except 否则就丢给上一层调用者处理
不该处理的异常就别处理 并非 try-except 写的多就程序更健壮更靠谱

出错了就返回 fail 即使不用 sentry 至少也应该同时记录一下 traceback.print_exc()
janus77
2018-10-29 14:32:52 +08:00
不是越多越好,但是该用的地方肯定要用的啊
p2pCoder
2018-10-29 14:35:22 +08:00
你还不会打日志,这是最大的问题
很多地方 try except 是必要的,这是程序健壮性必须的
后端接口,不要直接把 exception 直接抛给 接口调用方,无论调用方是 web 前端,还是其他服务
调用方并不关心你究竟又啥异常

楼主还是多向公司有经验的问问,日志打不好,排查线上问题是很老火的
owenliang
2018-10-29 14:54:42 +08:00
我觉得框架捕获就可以,业务代码别处理那么多异常。

框架捕获了该打日志打日志,该采集采集,能追查能报警就很好。
TheWalkingDead
2018-10-29 15:01:48 +08:00
这是打日志的问题,即使用了 try except,也可以完整的打印出异常栈
welkinzh
2018-10-29 15:03:11 +08:00
是日志没反映出问题,不能怪 try/except
xuanbg
2018-10-29 15:26:47 +08:00
异常处理里面没有业务逻辑的话,还是交给框架去捕获好了。
TommyLemon
2018-10-29 15:43:18 +08:00
必要的地方一定要用,尤其是涉及业务处理的地方,
例如 手机号已注册异常、订单已完成 /取消不允许改商品 /付款 等。

先 try-catch,然后 catch 内判断判断环境,
开发环境下重新 throw 出来,尽早暴露 bug 尽早解决,fail fast ;
线上环境就写日志,以便追踪错误。

在返回给 HTTP API 调用方(一般是写在 Controller 里面)前,
把 Exception 转成 错误码 status 和 错误信息 message,
毕竟人家可不想看到一堆后端的堆栈信息,而且没有 status 也不好处理。

还有线上环境千万不能因为部分接口异常导致整个服务挂掉,
虽然 SpringBoot 等框架会统一 catch 避免这种问题,
并在 Response Header 返回 status 和 message,
但还是自己 catch 到封装成业务状态码和错误信息更好,
尤其是在 业务错误码 和 HTTP status 有重合的情况下会不好区分,
HTTP status 更多地是用在连接状态上,
自定义的 status 是用于自己的业务处理状态。
TommyLemon
2018-10-29 15:53:02 +08:00
@TommyLemon 有些 SDK 抛的异常,有必要替换成你自己的,
例如
NoSuchMethodException("... did not find method getOrder, ..."),
DuplicatedEntryException("... phone is a unique column and 12345 already exist ..."),
可以换成自己封装的
ServerException("服务器内部错误") ,
ConflictException("手机号已注册")
等,
一方面可以更简单明确地告诉调用方出了什么问题,
另一方面可以避免信息泄露( SQLSyntaxError 里面可能会有 SQL 片段,暴露出 表名、字段名等)
flyingghost
2018-10-29 16:07:44 +08:00
1,理论上你应该把“出了任何问题,通过日志可以分析出原因”作为目标去追求。毕竟后端有很多很微妙的 bug 或者漏洞很难重现。日志应该是最有力的分析工具。如果分析不出来,说明你没记录好。
2,try/catch 我是这样使用的:
2.1,可预期的,自己可处理的一般会拆成小的 try 当场给结论或者当场恢复掉。
2.2,原则上不会给调用方暴露原始异常信息,一定是经过掩饰或者二次处理的信息。这个操作可以在业务层,也可以在中间件或者框架层。
2.3,至于具体谁负责,看情况。有时候多方共同处理 /记录然后 rethrow 出去给上层做不同层面的处理也是常见的。
zhangqilin
2018-10-29 16:24:10 +08:00
非常感谢
huahuajun9527
2018-10-29 16:57:40 +08:00
首先确定,定义好异常类型。一个函数的责任是有限的,出现不能处理的问题就往上抛,让上层调用者自己处理。

PS:并不是将异常打印出来就算处理异常!!!
itskingname
2018-10-29 17:09:35 +08:00
送你一个 Python 第三方库:tenacity
zhangwugui
2018-10-29 17:24:36 +08:00
一般不都是使用全局的异常处理来解决么,exceptionhander。只有在必要的时候显示用 try/catch 吧
glacer
2018-10-29 18:02:06 +08:00
任何可能出现运行时错误的地方都需要 try/catch,比如 HTTP 请求,数据库操作等。
如果错误能在 catch 块中被解决且不需要中断程序执行的,可在 catch 中修复继续执行。
如果错误无法被解决,则在 catch 中 raise 到上层处理。

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

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

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

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

© 2021 V2EX