我应该总是在`except`语句中指定一个异常类型吗?

时间:2013-02-10 11:43:44

标签: python exception pep8

使用PyCharm IDE时,使用没有异常类型的except:会触发IDE提醒此异常条款为Too broad

我应该忽略这个建议吗?或者是Pythonic总是具体的异常类型?

7 个答案:

答案 0 :(得分:74)

指定显式异常类型几乎总是更好。如果你使用一个裸except:子句,你可能最终会捕获除了你期望捕获的异常之外的异常 - 这可以隐藏错误或者当它们没有按照你期望的那样调试程序时更难。 p>

例如,如果要在数据库中插入行,则可能需要捕获指示该行已存在的异常,以便进行更新。

try:
    insert(connection, data)
except:
    update(connection, data)

如果指定一个裸except:,您还会收到一个套接字错误,指示数据库服务器已经崩溃。最好只捕获你知道如何处理的异常 - 程序通常在异常点失败而不是继续但是以奇怪的意外方式表现。

您可能希望使用裸except:的一种情况是您需要始终运行的程序的顶层,例如网络服务器。但是,你需要非常小心地记录异常,否则就不可能弄清楚出了什么问题。基本上,程序中最多只能有一个这样做。

所有这一切的必然结果是,您的代码永远不应该raise Exception('some message'),因为它会强制客户端代码使用except:(或except Exception: 几乎一样糟糕)。您应该定义一个特定于您想要发出的问题的异常(可能继承自某些内置异常子类,如ValueErrorTypeError)。或者你应该提出一个特定的内置异常。这使您的代码用户可以小心地捕获他们想要处理的异常。

答案 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)

始终指定例外类型,您不希望捕获许多类型,例如SyntaxErrorKeyboardInterruptMemoryError等。

答案 5 :(得分:2)

以下是我使用的地方,除了没有类型

  1. 快速而肮脏的原型制作
  2. 这是我的代码中未经检查的异常的主要用途

    1. 顶级main()函数,我记录每个未捕获的异常
    2. 我总是添加它,因此生产代码不会溢出堆栈跟踪

      1. 应用程序层之间
      2. 我有两种方法可以做到:

        • 第一种方法:当更高级别的层调用较低级别的函数时,它会将调用包装在类型的例外中以处理“最高”的较低级别异常。但我添加了一个通用的except语句,以检测较低级别函数中未处理的较低级别异常。

        我更喜欢这种方式,我发现更容易检测哪些异常应该被恰当地捕获:当更高级别记录较低级别异常时,我“更好地”看到问题

        • 第二种方法:较低级别层的每个顶级函数都将其代码包装在一个泛型中,除了它捕获该特定层上的所有未处理异常。

        有些同事更喜欢这种方式,因为它在较低级别的功能中保留较低级别的例外,它们“属于”。

答案 6 :(得分:-8)

试试这个:

try:
    #code
except ValueError:
    pass

我从这个链接得到了答案,如果有其他人遇到此问题Check it out