【问题标题】:What is the prefered way to deprecate a class and subclass弃用类和子类的首选方法是什么
【发布时间】:2014-07-02 07:47:46
【问题描述】:

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

目前我认为__init__() 会起作用,但它不会因为如果我不在子类上调用super() 就不会调用它。

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

我知道怎么用warn.warning()

我也不想使用装饰器。我只想在一个类上使用它,如果调用该类,它应该警告用户。

【问题讨论】:

标签: python


【解决方案1】:

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

发出警告,或者忽略它或引发异常。这 类别参数,如果给定,必须是一个警告类别类(见 以上);它默认为用户警告。或者消息可以是 警告实例,在这种情况下类别将被忽略并且 message.class 将被使用。在这种情况下,消息文本将是 字符串(消息)。如果特定的 发出的警告被警告过滤器更改为错误,请参阅 以上。

来自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

【讨论】:

    猜你喜欢
    • 2017-07-22
    • 2014-02-09
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 2018-06-15
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多