Python异常的最佳实践?

Ube*_*per 60 python exception

创建例外的最佳做法是什么?我刚看到这个,我不知道我是否应该感到恐惧或喜欢它.我在书中多次阅读异常永远不会持有字符串,因为字符串本身可以抛出异常.这有什么真相吗?

基本上我从脚本的理解是这样做,所以所有内部Python库将有一个共同的错误消息格式(迫切需要的东西)所以我可以理解为什么把错误消息字符串是一个好主意.(几乎每种方法都会抛出异常,因为完全不需要无效的通过).

有问题的代码如下:

"""
Base Exception, Error
"""
class Error(Exception):
    def __init__(self, message):
        self.message = message

    def __str__(self):
        return "[ERROR] %s\n" % str(self.message)

    def log(self):
        ret = "%s" % str(self.message)
        if(hasattr(self, "reason")):
            return "".join([ret, "\n==> %s" % str(self.reason)])
        return ret

class PCSException(Error):
    def __init__(self, message, reason = None):
        self.message = message
        self.reason = reason
    def __str__(self):
        ret = "[PCS_ERROR] %s\n" % str(self.message)
        if(self.reason != None):
            ret += "[REASON] %s\n" % str(self.reason)
        return ret
Run Code Online (Sandbox Code Playgroud)

这只是冰山一角,但有人可以给我一些洞察力,这是一个什么使这个可怕的想法?或者,如果有一个更好的异常编码过程/风格.

Eli*_*sky 84

强大的异常处理(在Python中) - 我之前写过的"Python异常的最佳实践"博客文章.你可能会发现它很有用.

博客的一些关键点:

永远不要使用流量控制的例外

异常情况存在例外情况:不属于正常执行的事件.

如果找不到模式,请考虑返回-1的字符串'find',但索引超出字符串结尾会引发异常.找不到字符串是正常执行.

处理知道如何处理它们的级别的异常

...

最好的地方是可以处理异常的那段代码.对于某些异常,例如编程错误(例如IndexError,TypeError,NameError等),异常最好留给程序员/用户,因为"处理"它们只会隐藏真正的错误.

总是问"这是处理这个例外的正确位置吗?" 并注意捕捉所有异常.

记录代码抛出的异常

...

考虑代码可能引发的异常将帮助您编写更好,更安全和更封装的代码

  • 我不确定我记得在2009年发布这个答案时的习惯:-)随意建议编辑 (4认同)
  • 习惯上提供外部链接的概要. (3认同)
  • 尽管如此,他的文章仍然值得一读,并为回答这个问题做出了宝贵的贡献。 (2认同)
  • 使用异常进行流控制不是很标准的鼓励做法吗?这就是try / catch / else模式的重点,不是吗?Python中的for循环使用异常来知道何时停止for循环中的迭代器。在不隐式使用异常的情况下,进行基本程序控制几乎是不可能的。 (2认同)

S.L*_*ott 34

我在书中多次阅读异常永远不会持有字符串,因为字符串本身可以抛出异常.这有什么真相吗?

什么?

请提供参考或链接.这完全是不真实的.

由于所有对象都可以抛出异常,因此该逻辑不会在异常中包含任何对象.

不,"没有字符串"在Python上下文中简直就是疯了.也许您是在C++上下文中阅读它.


编辑

曾几何时(回到过去),您可以通过名称而不是实际的类来引发Python异常.

raise "SomeNameOfAnExceptionClass"
Run Code Online (Sandbox Code Playgroud)

这是不好的.但这包括异常中的字符串.这是使用字符串而不是实际的类对象来命名异常.在2.5中,这仍然有效,但会收到弃用警告.

也许这就是你读到的"不要用字符串名称引发异常"

  • 也许它指的是你不应该为多种异常情况使用Exception类.像MyFrameworkException('File not found')和MyFrameworkException('Database connection unavailable'). (7认同)
  • 呃,我不认为你对如何提高工作是正确的.raise用于接受字符串,因为该字符串*将是异常*.它不会占用字符串并实例化其他一些对象,它会直接抛出字符串.或者我想.这就是为什么有这样的python代码:raise"这是我很好的详细错误信息" (2认同)

Gra*_*and 7

我相信反对使用字符串创建异常的建议来自"学习Python"(O'Reilly).在标题为String Exceptions Are Right Out的部分中!,它指出了(现已删除)使用任意字符串直接创建异常的能力.

它给出的代码是一个例子:

myexc = "My exception string"
try:
    raise myexc
except myexc:
    print ('caught')
Run Code Online (Sandbox Code Playgroud)

这是第四版的p858(平装本).


mil*_*ose 5

第一印象是对于异常来说代码太多了。

格式化异常应该在记录器配置中完成。日志记录本身也是如此。

它还重新定义了标准(和已弃用的)消息属性,并且不调用超类构造函数。(这可能会或可能不会破坏Python 3.0异常链接,我没有尝试过,因为我正在运行2.6)

额外代码的大部分功能可以使用 BaseException.args 来实现,通过将以下内容记录为“消息”:

'\n==> '.join(exception.args)
Run Code Online (Sandbox Code Playgroud)

我认为,如果可以使用通用/惯用机制来完成某件事,那么尤其应该在异常处理中这样做。(异常是一种应用程序层发出信号的机制。)

就我个人而言,我会尽量避免任何超出

class SomeException(Exception): pass
Run Code Online (Sandbox Code Playgroud)

(免责声明:回答主观,可能是根据问题的性质。)