Pythonic,自定义警告

时间:2012-04-25 18:51:13

标签: python python-3.x warnings

基本问题:制作我自己的自定义警告类的最佳Pythonic /逻辑方法是什么?我应该继承哪些正确的警告和异常类?

动机:我正在编写的库的要求指定如果MyContainer对象c包含项x和库的调用者尝试将x的“重复” - 称之为y - 调入c,向调用者发出警告并放置c.my_transformation_method(x, y)的返回值进入c以替换x。换句话说,MyContainer s将替换带有重复项的元素,但必须在这样做时警告用户。

根据我的阅读,警告图书馆来电者关于非致命行为的最灵活方式是使用warnings standard module。它允许调用者在其认为合适时处理警告,从忽略警告到将其视为错误做任何事情。 (请注意,我使用的是Python 3,但我不认为这对这个问题至关重要。)

示例:我所做的是定义了以下警告子类:

class DuplicateItemWarning(UserWarning, ValueError):
    pass

然后add() MyContainer方法在检测到尝试插入重复项时调用warnings.warn('detected duplicate', DuplicateItemWarning)

具体问题:

  1. 我应该如上所述继承UserWarning,还是仅仅升级Warning

  2. 子类ValueError(在上面的示例中,仅在ValueErrorWarning之间的MRO中插入Exception)似乎在语义上合理调用者希望将警告视为错误。我有没有看到这个缺点?

  3. 我在StackOverflow上找不到关于自定义警告类的任何问题。这是因为Python程序员甚至不喜欢使用warnings模块吗?

1 个答案:

答案 0 :(得分:4)

在阅读有关警告框架和警告文档的PEP 230之后,我想我已经回答了您的问题:

  1. UserWarning和所有其他人都是警告类别,他们似乎没有其他角色而不仅仅是分类。这样,您可以在生产环境中过滤掉它们。因此,基本上,如果警告不属于任何其他类别,您可以从Warning继承子类。如果上下文中的 UserWarningRuntimeWarning似乎已足够,只需使用它们。

  2. Warning已经Exception了。因此,从技术上讲,要将它们“捕获”为错误,您只需更改过滤器,无需从任何XXXError子类化。现在,这一切都是有意义的。如果警告是关于传递的值,则可以从ValueError继承,特别是如果存在许多不同的自定义警告,您可能希望调用者一次“捕获”关于值的所有警告。

    try:
         # do something
    except MyCustomWarningOne:
        # do something else
    except MyCustomWarningTwo:
        # do something else also
    except ValueError: # or RuntimeWarning if you subclass from it
        # catch some other warning (both of these subclass from ValueError for example)
    
  3. warnings模块是Guido van Rossum的想法。 (见PEP 230)。如果那不是Pythonic就足够......:D