是否可以弃用Exception类?

时间:2016-11-11 09:36:41

标签: python exception

情况:我的库中有一些自定义的异常类,用户在其代码中使用它们。出于某种原因,我想重命名其中一个例外并弃用旧例外。

将旧的异常保留为别名并不困难:

class MyNewError(ValueError):
    pass

MyOldError = MyNewError

但最终我想删除我的库的旧错误名称,因此我希望在下游代码中使用此自定义异常的用户通过DeprecationWarning通知此错误将被删除。

但是我想在下面的用例中提出DeprecationWarning(比如我的包含自定义异常的库名为mypackage):

# downstream user code
import mypackage

...

try:
    ....
except mypackage.MyOldError:
    ....

所以我想在用户尝试捕捉错误时提出警告,而不仅仅是当用户提出错误时。

有可能以某种方式做到这一点吗? (因为用户没有在这里调用我可以提出弃用警告的函数)

2 个答案:

答案 0 :(得分:4)

您可以从this answer应用黑客/技巧,将您的模块转换为类并拦截__getattr__()操作:

<强> mypackage的/ __初始化__吡啶

import sys
import warnings

class MyNewError(ValueError):
    pass

MyOldError = MyNewError

def foo():
    print('mypackage.foo(): raising MyNewError')
    raise MyNewError()

class Wrapper(object):
    def __init__(self, wrapped):
        self.wrapped = wrapped

    def __getattr__(self, name):
        if name == 'MyOldError':
            warnings.warn('MyOldError is deprecated, use MyNewError')

        return getattr(self.wrapped, name)

sys.modules[__name__] = Wrapper(sys.modules[__name__])

<强> test.py

import mypackage

try:
    mypackage.foo()
except mypackage.MyOldError:
    print('Caught mypackage.MyOldError')

<强>输出

$ python test.py 
mypackage.foo(): raising MyNewError
mypackage/__init__.py:18: UserWarning: MyOldError is deprecated, use MyNewError
  warnings.warn('MyOldError is deprecated, please use MyNewError')
Caught mypackage.MyOldError

答案 1 :(得分:2)

当然可以在异常中引发异常,但如果用户不期望它,则可能会导致问题。假设这只是你帖子中的一个失误,并且你没有想要提出的DeprecationWarning例外,你可以执行以下操作:

class MyOldError(MyNewError):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        deprecation_warning('Deprecated, please use MyNewError')

>>> raise MyOldError
Deprecated, please use MyNewError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.MyOldError
>>>