使用PyCharm IDE时,使用except:
无异常类型会触发IDE提醒此异常子句为Too broad
。
我应该忽略这个建议吗?还是总是特定于异常类型的Pythonic?
使用PyCharm IDE时,使用except:
无异常类型会触发IDE提醒此异常子句为Too broad
。
我应该忽略这个建议吗?还是总是特定于异常类型的Pythonic?
Answers:
指定显式异常类型几乎总是更好。如果使用裸except:
子句,则最终可能会捕获到您期望捕获的异常以外的异常-这可能会隐藏错误或使程序无法按预期运行时更难以调试。
例如,如果要在数据库中插入行,则可能要捕获一个异常,该异常表明该行已存在,因此可以进行更新。
try:
insert(connection, data)
except:
update(connection, data)
如果指定了裸except:
,您还将捕获到一个套接字错误,指示数据库服务器已倒塌。最好只捕获您知道如何处理的异常-程序在异常发生时失败通常比继续执行但以奇怪的意外方式执行更好。
您可能希望使用裸机的一种情况except:
是始终需要运行的程序的顶层,例如网络服务器。但是然后,您需要非常小心地记录异常,否则将无法找出问题所在。基本上,执行此操作的程序中最多只能有一个位置。
其推论这一切是你的代码不应该这样做raise Exception('some message')
,因为它迫使客户端代码使用except:
(或except Exception:
这是几乎一样糟糕)。您应该定义一个特定于您要发信号的问题的异常(也许从某些内置的异常子类(例如ValueError
或TypeError
)继承)。或者,您应该引发特定的内置异常。这使您的代码用户可以小心地捕获他们想要处理的异常。
except:
还捕获了(以及其他许多东西)NameError
和AttributeError
,因此,如果您在try
块中拼错了某些内容(例如,insert_one
由于有人未如愿以偿地重视一致性,实际上会调用“插入”函数),总是默默地尝试update()
。
main()
)?
except Exception:
将捕获NameError
和AttributeError
太。是什么让裸except:
如此糟糕的是,它捕获没有业务被抓,如东西SystemExit
(当你打电话提出exit
或者sys.exit
,现在你已经防止预期的出口)和KeyboardInterrupt
(同样,如果用户命中Ctrl-C
,您可能不希望保持运行只是为了sp他们)。只有后者才是真正有意义的捕获对象,应明确捕获它。至少except Exception:
让这两个正常传播。
您不应忽略口译员给您的建议。
摘自《PEP-8 Python样式指南》:
捕获异常时,请尽可能提及特定的异常,而不要使用裸露的except:子句。
例如,使用:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
单独的except:子句将捕获SystemExit和KeyboardInterrupt异常,这使得使用Control-C中断程序更加困难,并且可以掩盖其他问题。如果要捕获所有表示程序错误的异常,请使用Exception:除外(裸除等效于BaseException:除外)。
一个好的经验法则是将裸'except'子句的使用限制为两种情况:
如果异常处理程序将打印输出或记录回溯;至少用户会意识到发生了错误。如果代码需要执行一些清理工作,但随后让异常通过提高向上传播。试试...最终可能是处理这种情况的更好方法。
并不特定于Python。
异常的全部要点是尽可能在引起问题的地方进行处理。
因此,您保留可能在特殊情况下可能引发问题和解决方案的代码。
问题是您不知道一段代码可能引发的所有异常。您所知道的就是,如果这是一个“找不到文件”异常,则可以将其捕获并提示用户获取执行该功能或取消该功能的文件。
如果您尝试使用catch,那么无论您的文件例程出现什么问题(只读,权限,UAC,不是真正的pdf等),每个文件都会放入未找到catch的文件中,并且您的用户尖叫“但它在那里,此代码是废话”
现在有几种情况,您可能会抓住一切,但是应该有意识地选择它们。
它们会被捕获,撤消某些本地操作(例如,创建或锁定资源,(例如,打开磁盘上的文件以进行写入),然后再次引发该异常,以在更高级别进行处理)
另一个是您,您不管它为什么出错。例如打印。您可能会遇到一个麻烦,那就是您的打印机出现问题,请解决该问题,不要因此而终止应用程序。如果您的代码使用某种时间表执行一系列单独的任务,那将是徒劳的,因为其中一个任务失败,您将希望整个事情死掉。
注意:如果执行上述操作,则我不建议您进行某种程度的异常日志记录,例如,尝试捕获日志结尾足够高。
您还将捕获到Control-C,因此,除非再次“抛出”它,否则不要这样做。但是,在这种情况下,您应该使用“ finally”。
始终指定的异常类型,也有很多种类,你不想抓,像SyntaxError
,KeyboardInterrupt
,MemoryError
等等。
except Exception:
避免使用我们不想捕获的上述类型?
except Exception
很好
except Exception
捕获SyntaxError
并且MemoryError
因为它是它们的基类。KeyboardInterrupt
,SystemExit
(由引发sys.exit()
)未被捕获(它们是直接的BaseException子类)
这是我在没有类型的情况下使用的地方
这是我的代码中未经检查的异常的主要用途
我总是添加它,以便生产代码不会溢出堆栈跟踪
我有两种方法可以做到:
我更喜欢这种方式,我发现更容易检测应该适当捕获哪些异常:当较高级别的日志记录了较低级别的异常时,我可以更好地“查看”问题
一些同事更喜欢这种方式,因为在“所属”的较低级别的函数中保留了较低级别的异常。