如何在 Python 中捕获异常时引发 DeprecationWarning?

5

我编写了一个库,有时会触发异常。我想要废弃其中的一种异常,并建议人们停止捕获它们,在警告信息中提供建议。但是如何让一个异常在被捕获时发出DeprecationWarning 呢?

库代码

import warnings

class MyException(ValueError):
    ...
    warnings.warn(
        "MyException is deprecated and will soon be replaced by `ValueError`.",
        DeprecationWarning,
        stacklevel=2,
    )
    ...

def something():
    raise MyException()

用户代码

try:
    mylib.something()
except MyException: # <-- raise a DeprecationWarning here
    pass

我该如何修改MyException以实现这个目的?


用户自定义异常或库代码> - Sandrin Joy
你已经编辑了你的问题,使得没有明确的过渡路径。except MyException已经被弃用,但是没有好的替代方案供用户使用。 - user2357112
相关:__getattr__模块 - wim
问题是,如果捕获此异常已被弃用,您的用户还应该做什么? - a_guest
2个回答

10
你做不到。在except MyException发生的逻辑中,没有任何可定制的内容。特别是,它完全忽略了像__instancecheck____subclasscheck__这样的东西,因此你不能钩入决定异常是否匹配异常类的过程之中。
你能接近的方法是当用户尝试使用from yourmodule import MyExceptionyourmodule.MyException访问你的异常类时发出警告。你可以通过模块的__getattr__实现这一点:
class MyException(ValueError):
    ...

# access _MyException instead of MyException to avoid warning
# useful if other submodules of a package need to use this exception
# also use _MyException within this file - module __getattr__ won't apply.
_MyException = MyException
del MyException

def __getattr__(name):
    if name == 'MyException':
        # issue warning
        return _MyException
    raise AttributeError

无法按照原样工作。只有在正常方式下找不到名称时,才会调用__getattr__ - wim
@wim:哦,糟糕 - 我本来想写一个 del MyException 的,但是我忘了写。现在已经修复了。 - user2357112
2
+1 这是正确的方式,而弃用名称实际上是 PEP 中模块 __getattr__ 特性的第一个原理 - wim

-1

尝试使用这个:

import warnings


class MyOtherException(Exception):
    pass


class MyException(MyOtherException):
    def __init__(self):
        warnings.warn(
            "MyException is deprecated and will soon be replaced by `MyOtherException`.",
            DeprecationWarning,
            stacklevel=2,
        )


if __name__ == "__main__":
    try:
        mylib.something()
    except Exception:
        raise MyException()



我只能编辑“库代码”,而不能编辑“用户代码”,因此我无法假设任何内容进入except块。不能保证用户会引发“MyException”。 - azmeuk
这是没有抓住重点。用户代码可能会捕获MyException类,而从未实例化过它。 - wim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接