Pythonic,自定义警告

wks*_*rtz 10 python warnings python-3.x

基本问题:制作我自己的自定义警告类的最Pythonic /逻辑方法是什么?我应该进行子类化的正确警告和异常类是什么?

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

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

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

class DuplicateItemWarning(UserWarning, ValueError):
    pass
Run Code Online (Sandbox Code Playgroud)

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

具体问题:

  1. 我应该UserWarning如上所述进行子类化,还是仅仅进行次级转换Warning

  2. 这似乎语义明智的子类ValueError(在上述例子中,仅插入ValueError之间在MRO WarningException在呼叫者想要治疗警告视为错误情况).我有没有看到这个缺点?

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

jad*_*k94 11

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

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

  2. Warnings 已经是Exceptions。因此,从技术上讲,要“捕获”它们作为错误,您只需更改过滤器,无需从任何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)
    
    Run Code Online (Sandbox Code Playgroud)
  3. warnings模块是 Guido van Rossum 的想法。(参见 PEP 230)。如果这还不够Pythonic...:D