Python 3.4中的自定义异常代码和消息

1 投票
1 回答
1978 浏览
提问于 2025-04-18 15:06

我想要创建一个自定义的错误代码和消息数据库,然后在抛出异常时使用它(在Python 3.4中)。于是我做了以下的事情:

class RecipeError(Exception):

    # Custom error codes
    ERRBADFLAVORMIX = 1
    ERRNOINGREDIENTS = ERRBADFLAVORMIX + 1

    # Custom messages
    ERRMSG = {ERRBADFLAVORMIX: "Bad flavor mix",
              ERRNOINGREDIENTS: "No ingredients to mix"}

raise RecipeError(RecipeError.ERRMSG[RecipeError.ERRBADFLAVORMIX])

这样做的效果是我预期的,但这个raise语句看起来实在太复杂了。当然,我可以用更简洁的方式来存储这些值,但我真正想知道的是:我能不能直接用raise RecipeError(code),然后让RecipeError自己去处理获取消息的工作呢?

1 个回答

3

当然可以。异常类其实就是普通的类,所以你可以定义自己的 __init__ 方法,并适当地调用 super

class RecipeError(BaseException):
    # existing stuff
    def __init__(self, code):
        super().__init__(self, RecipeError.ERRMSG[code])

你可能还想保存这段代码:

class RecipeError(BaseException):
    # existing stuff
    def __init__(self, code):
        msg = RecipeError.ERRMSG[code]
        super().__init__(self, msg)
        self.code, self.msg = code, msg

可以看看标准库中的异常信息(在3.4版本中相当不错,虽然以后还会有更多变化……),了解一下哪些信息可能对你有用。


一些附带说明:


首先,使用子类可能比使用错误代码更好。例如,如果有人想写代码来捕捉 ERRBADFLAVORMIX 这个错误,但不想捕捉 ERRNOINGREDIENTS,他们需要这样做:

try:
    follow_recipe()
except RecipeError as e:
    if e != RecipeError.ERRBADFLAVORMIX:
        raise
    print('Bad flavor, bad!')

而如果你使用了子类的话:

try:
    follow_recipe():
except BadFlavorRecipeError as e:
    print('Bad flavor, bad!')

这正是为什么Python不再有一个庞大的 OSError 和一个需要你去判断的 errno 值,而是有像 FileNotFoundError 这样的独立子类。


如果你确实想使用错误代码,可能可以考虑使用 Enum,或者在PyPI上找一些更高级的枚举类型,这样可以更方便地为每个错误附加自定义字符串。


你几乎不想从 BaseException 继承,除非你特别想确保你的异常不会被捕捉到。

撰写回答