Python异常的最佳实践?

时间:2009-05-08 12:44:43

标签: 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

这只是冰山一角,但有人可以给我一些洞察力,让我知道这是一个多么糟糕的主意吗?或者,如果有更好的异常编码过程/风格。

5 个答案:

答案 0 :(得分:82)

Robust exception handling (in Python) - 我之前写过的“Python异常的最佳做法”博客文章。您可能会发现它很有用。

博客中的一些要点:

  

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

     

特殊情况存在异常:不是a的事件   正常执行的一部分。

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

  

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

     

...

     

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

总是问“这是处理此例外的正确位置吗?”并且要小心捕捉所有例外。

  

记录代码抛出的异常

     

...

     

考虑代码可能抛出的异常将对您有所帮助   写出更好,更安全,更封装的代码

答案 1 :(得分:32)

  

我在书中读了好几遍   例外永远不应该持有   字符串,因为字符串本身可以   抛出异常。任何真实的事实   此?

什么?

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

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

不,“无字符串”在Python上下文中简直就是疯了。也许你是在C ++环境中阅读的。


修改

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

raise "SomeNameOfAnExceptionClass"

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

也许这就是您所读到的“不要使用字符串名称引发异常”

答案 2 :(得分:5)

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

它给出的代码是:

myexc = "My exception string"
try:
    raise myexc
except myexc:
    print ('caught')

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

答案 3 :(得分:4)

第一印象是异常的代码太多了。

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

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

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

'\n==> '.join(exception.args)

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

就个人而言,我试图避免除

之外的任何事情
class SomeException(Exception): pass

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

答案 4 :(得分:0)

class Error(Exception):
    """Base class for other exceptions"""
    pass

class empty_string_error(Error):
    """Raised when the input value is too large"""
    pass
while(1):
    try:
        if("Your Condition"):
            raise empty_string_error
        else:
            print("OUTPUT")
    except empty_string_error:
        print("APT MESSAGE")
        print(" ")
    finally:
        pint("Mandatory code")