异常处理与if-else哪种错误处理方式更优?以subprocess.run场景为例
subprocess执行结果校验方案对比
两种方案的优劣势
if-else校验returncode方案
- 优势
- 逻辑透明可控,后续需要针对不同非0返回码做差异化处理时,无需调整代码结构,直接加分支即可
- 不会误吞其他异常:命令执行本身的错误(比如目标路径不存在、当前用户无执行权限、参数非法等)会正常抛出,不会被错误处理逻辑掩盖,方便排查问题
- 无额外的异常生成、捕获开销,虽然在这个场景下性能差异可以忽略
- 劣势
- 代码冗余度高,每次调用
subprocess.run都需要手动写返回码判断逻辑,多处调用时会产生大量重复代码 - 容易漏处理:如果忘记写returncode判断,程序会默认命令执行成功继续向下跑,隐藏故障
- 代码冗余度高,每次调用
try-except配合check=True方案
- 优势
- 代码更简洁,subprocess内部已经封装了返回码校验逻辑,只要返回非0就会抛出
CalledProcessError异常,减少重复代码 - 不会漏校验:只要加了
check=True参数,执行失败一定会抛出异常,不会出现忘记判断返回码的问题
- 代码更简洁,subprocess内部已经封装了返回码校验逻辑,只要返回非0就会抛出
- 劣势
- 你示例中直接捕获
Exception是严重的错误实践,会误吞所有类型的异常,包括变量名拼写错误、内存溢出等和命令执行结果无关的故障,只打一行日志会极大提升排查难度,必须精准捕获subprocess.CalledProcessError - 后续需要处理不同返回码时,需要从异常对象的
returncode属性取值,相比直接从run返回的对象取属性多了一层转换
- 你示例中直接捕获
针对你的场景的推荐
你当前仅需要判断命令执行成功/失败,打印错误后终止流程,更推荐使用修正后的try-except方案:
import subprocess def someFunction(): try: op = subprocess.run( ['./someCommand', 'andItsOptions'], cwd=self.INSTALLATION_PATH_TO_THE_COMMAND_BEING_RUN, check=True ) self.logger.info('successfully executed the command') except subprocess.CalledProcessError as e: self.logger.error(f'error while executing the command, program exits with return code: {e.returncode}') return False
如果后续你需要扩展对不同返回码的处理逻辑,比如返回1要重试、返回2要提示用户输入参数,直接切换为if-else方案即可。
内容的提问来源于stack exchange,提问作者qre0ct
相关产品推荐
相关产品推荐

