基本问题:制作我自己的自定义警告类的最佳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)
。
具体问题:
我应该如上所述继承UserWarning
,还是仅仅升级Warning
?
子类ValueError
(在上面的示例中,仅在ValueError
和Warning
之间的MRO中插入Exception
)似乎在语义上合理调用者希望将警告视为错误。我有没有看到这个缺点?
我在StackOverflow上找不到关于自定义警告类的任何问题。这是因为Python程序员甚至不喜欢使用warnings
模块吗?
答案 0 :(得分:4)
在阅读有关警告框架和警告文档的PEP 230之后,我想我已经回答了您的问题:
UserWarning
和所有其他人都是警告类别,他们似乎没有其他角色而不仅仅是分类。这样,您可以在生产环境中过滤掉它们。因此,基本上,如果警告不属于任何其他类别,您可以从Warning
继承子类。如果上下文中的 ,UserWarning
或RuntimeWarning
似乎已足够,只需使用它们。
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)
warnings
模块是Guido van Rossum的想法。 (见PEP 230)。如果那不是Pythonic就足够......:D