使用PyCharm IDE时,使用没有异常类型的except:
会触发IDE提醒此异常条款为Too broad
。
我应该忽略这个建议吗?或者是Pythonic总是具体的异常类型?
答案 0 :(得分:74)
指定显式异常类型几乎总是更好。如果你使用一个裸except:
子句,你可能最终会捕获除了你期望捕获的异常之外的异常 - 这可以隐藏错误或者当它们没有按照你期望的那样调试程序时更难。 p>
例如,如果要在数据库中插入行,则可能需要捕获指示该行已存在的异常,以便进行更新。
try:
insert(connection, data)
except:
update(connection, data)
如果指定一个裸except:
,您还会收到一个套接字错误,指示数据库服务器已经崩溃。最好只捕获你知道如何处理的异常 - 程序通常在异常点失败而不是继续但是以奇怪的意外方式表现。
您可能希望使用裸except:
的一种情况是您需要始终运行的程序的顶层,例如网络服务器。但是,你需要非常小心地记录异常,否则就不可能弄清楚出了什么问题。基本上,程序中最多只能有一个这样做。
所有这一切的必然结果是,您的代码永远不应该raise Exception('some message')
,因为它会强制客户端代码使用except:
(或except Exception:
几乎一样糟糕)。您应该定义一个特定于您想要发出的问题的异常(可能继承自某些内置异常子类,如ValueError
或TypeError
)。或者你应该提出一个特定的内置异常。这使您的代码用户可以小心地捕获他们想要处理的异常。
答案 1 :(得分:32)
你不应该忽视口译员给你的建议。
来自PEP-8 Python样式指南:
捕获异常时,请及时提及特定异常 可能而不是使用bare except:子句。
例如,使用:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
一个裸的except:子句将捕获SystemExit和KeyboardInterrupt异常,使其更难 用Control-C中断程序,可以掩饰其他问题。 如果要捕获发出程序错误信号的所有异常,请使用 除了异常:(裸除了相当于除外 BaseException:)
一个好的经验法则是将裸'除了'子句的使用限制为两个 例:
如果异常处理程序将打印出来或记录 追溯;至少用户会意识到发生了错误。 如果代码需要做一些清理工作,那么就让异常 通过加注向上传播。试试......终于可以成为更好的方法了 处理这种情况。
答案 2 :(得分:8)
这对Python没有特别的说明。
例外的全部意义在于尽可能地将问题处理到尽可能接近的地方。
因此,您可以保留在特殊情况下可能触发问题的代码以及彼此“下一步”的解决方案。
问题是你无法知道一段代码可能抛出的所有异常。你可以知道的是,如果它是一个文件未找到异常,那么你可以捕获它并提示用户获取一个执行或取消该功能。
如果你把try catch放到那个,那么无论你的文件例程中有什么问题(只读,权限,UAC,不是真正的pdf等),每个人都会进入你的文件找不到catch,而你的用户正在尖叫“但它就在那里,这段代码就是废话”
现在有几种情况你可能会抓住所有东西,但应该有意识地选择它们。
它们是catch,撤消一些本地操作(例如创建或锁定资源,(例如在磁盘上打开文件以进行写入),然后再次抛出异常,以便在更高级别处理)
另一个你不在乎为什么会出错。例如打印。你可能有一个全面的问题,说你的打印机有问题,请整理出来,而不是因为它而杀死应用程序。如果您的代码使用某种计划执行一系列单独的任务,Ona类似的徒劳,您将不希望整个事情死亡,因为其中一个任务失败了。
注意如果您执行上述操作,我不建议使用某种异常日志记录,例如:尝试捕获日志结束,足够高。
答案 3 :(得分:3)
你也会抓住,例如控制-C与此,所以不要这样做,除非你再次“扔”它。但是,在这种情况下,你应该使用“finally”。
答案 4 :(得分:3)
始终指定例外类型,您不希望捕获许多类型,例如SyntaxError
,KeyboardInterrupt
,MemoryError
等。
答案 5 :(得分:2)
以下是我使用的地方,除了没有类型
这是我的代码中未经检查的异常的主要用途
我总是添加它,因此生产代码不会溢出堆栈跟踪
我有两种方法可以做到:
我更喜欢这种方式,我发现更容易检测哪些异常应该被恰当地捕获:当更高级别记录较低级别异常时,我“更好地”看到问题
有些同事更喜欢这种方式,因为它在较低级别的功能中保留较低级别的例外,它们“属于”。
答案 6 :(得分:-8)