19

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

动机:我正在编写的库的要求指定,如果一个MyContainer对象c包含一个项目x,并且库的调用者试图将一个“重复” x——调用它y——放入c,则会向调用者发出警告,并且的返回值c.my_transformation_method(x, y)被放入c替换x。换句话说,MyContainers 将用它们的重复元素替换元素,但这样做时必须警告用户。

根据我的阅读,警告库调用者有关非致命操作的最灵活方法是使用警告标准模块。它允许调用者在它认为合适的时候处理警告,做任何事情,从忽略警告到将它们视为错误。(请注意,我使用的是 Python 3,但我不认为这对这里的问题至关重要。)

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

class DuplicateItemWarning(UserWarning, ValueError):
    pass

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

具体问题:

  1. 我应该UserWarning像上面那样子类化,还是只是子类化Warning

  2. 如果调用者想要将警告视为错误,则子类ValueError(在上面的示例中,它仅插入ValueError到 MRO 之间Warning)在语义上似乎是明智的。Exception我没有看到这个有缺点吗?

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

4

1 回答 1

6

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

  1. UserWarning而所有其他都是警告类别,它们似乎除了分类之外没有其他作用。例如,通过这种方式,您可以在生产环境中将它们过滤掉。因此,基本上,Warning如果警告不属于任何其他类别,您可以从子类化。如果在上下文中UserWarning或者RuntimeWarning看起来足够,就使用它们。

  2. Warnings已经Exception是s了。因此,从技术上讲,要将它们“捕获”为错误,您只需要更改过滤器,无需从任何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

于 2012-04-25T20:16:48.377 回答