弃用类和子类的首选方法是什么

时间:2014-07-02 07:47:47

标签: python

我如何在Python中弃用类及其子类?

目前我认为__init__()可以正常工作,但它没有,因为如果我不在子类上调用super(),它就不会被调用。

编辑: Okai在我的问题上缺少一些信息。

我知道如何使用warn.warning()

另外,我不想使用Decorater。我想在一个类上使用它,如果调用该类,它应该警告用户。

1 个答案:

答案 0 :(得分:4)

您正在寻找warnings.warn(message[, category[, stacklevel]])

  

发出警告,或者忽略它或引发异常。该   如果给定,则类别参数必须是警告类别类(请参阅   以上);它默认为UserWarning。或者消息可以是a   警告实例,在这种情况下类别将被忽略   消息。将使用。在这种情况下,消息文本将是   STR(消息)。如果特定的话,此函数会引发异常   发出的警告由警告过滤器更改为错误   上方。

来自here

import functools
import inspect
import os
import warnings


class _DeprecatedDecorator(object):
    MESSAGE = "%s is @deprecated"

    def __call__(self, symbol):
        if not inspect.isclass(symbol):
            raise TypeError("only classes can be @deprecated")

        warnings.filterwarnings('default',
                                message=self.MESSAGE % r'\w+',
                                category=DeprecationWarning)
        return self._wrap_class(symbol)

    def _wrap_class(self, cls):
        previous_ctor = cls.__init__

        @functools.wraps(previous_ctor)
        def new_ctor(*args, **kwargs):
            self._warn(cls.__name__)
            return previous_ctor(*args, **kwargs)

        cls.__init__ = new_ctor
        return cls

    def _warn(self, name):
        warnings.warn(self.MESSAGE % name, DeprecationWarning,
                      stacklevel=self._compute_stacklevel())

    def _compute_stacklevel(self):
        this_file, _ = os.path.splitext(__file__)
        app_code_dir = self._get_app_code_dir()

        def is_relevant(filename):
            return filename.startswith(app_code_dir) and not \
                filename.startswith(this_file)

        stack = self._get_callstack()
        stack.pop(0)  # omit this function's frame

        frame = None
        try:
            for i, frame in enumerate(stack, 1):
                filename = frame.f_code.co_filename
                if is_relevant(filename):
                    return i
        finally:
            del frame
            del stack

        return 0

    def _get_app_code_dir(self):
        import myapplication  # root package for the app
        app_dir = os.path.dirname(myapplication.__file__)
        return os.path.join(app_dir, '')  # ensure trailing slash

    def _get_callstack(self):
        frame = inspect.currentframe()
        frame = frame.f_back  # omit this function's frame

        stack = []
        try:
            while frame:
                stack.append(frame)
                frame = frame.f_back
        finally:
            del frame

        return stack

deprecated = _DeprecatedDecorator()
del _DeprecatedDecorator