Python 2.x 元类生成的包装器中断检查

发布于 2024-12-09 06:21:39 字数 2385 浏览 1 评论 0原文

我遇到一个问题,我使用元类包装了一些类方法,但现在如果我使用内置的 help() 方法,这些方法将显示为包装器而不是原始方法。

# Example:

class MetaBuilderModule(type):

    @staticmethod
    def time_method(method):
        @functools.wraps(method)
        def __wrapper(self, *args, **kwargs):
            if self.__timingstatus__[method.__name__]:
                return method(self, *args, **kwargs)

            else:
                # Set the timing status of the method to True so that we don't
                # time any inherited methods.
                self.__timingstatus__[method.__name__] = True

                start = time.time()
                finish = None
                result = None

                # Put the result behind a try / except so that if we get an error
                # within the method we can still reset the timing status.
                try:
                    result = method(self, *args, **kwargs)
                except Exception:
                    exc_type, exc_value, exc_traceback = sys.exc_info()
                    traceback.print_exception(exc_type, exc_value, exc_traceback)
                    self.__timingstatus__[method.__name__] = False
                    return False

                finish = time.time()

                sys.stdout.write('Instance method \'%s\' of BuilderModule class'
                    ' took %0.3fs to execute.\n' %(method.__name__, (finish - start)))

                # Reset the timing status.
                self.__timingstatus__[method.__name__] = False
                return result

        return __wrapper


    def __new__(cls, name, bases, attrs):
        # Create the __timingstatus__ dictionary that helps stop timers being
        # triggered by inherited methods.
        attrs['__timingstatus__'] = dict()

        for attr in ['__init__', 'run']:
            attrs['__timingstatus__'][attr] = False

            if not attr in attrs:
                continue

            attrs[attr] = cls.time_method(attrs[attr])

        return super(MetaBuilderModule, cls).__new__(cls, name, bases, attrs)

正如您所看到的,我已将 @functools.wraps 装饰器添加到 __wrapper 方法中,以便至少我获得正确的方法名称,但我仍然没有获得正确的参数。

Example:

 |  Methods defined here:
 |  
 |    __init__(self, *args, **kwargs)

我看过一些建议猴子修补 inspect.getargspec 的文章,但我不认为这是一个实用的解决方案。

有人可以建议其他黑魔法吗?

干杯,

CB

I'm having an issue where I have wrapped some class methods using a metaclass, but now if I use the help() built-in the methods are displayed as the wrapper instead of the original method.

# Example:

class MetaBuilderModule(type):

    @staticmethod
    def time_method(method):
        @functools.wraps(method)
        def __wrapper(self, *args, **kwargs):
            if self.__timingstatus__[method.__name__]:
                return method(self, *args, **kwargs)

            else:
                # Set the timing status of the method to True so that we don't
                # time any inherited methods.
                self.__timingstatus__[method.__name__] = True

                start = time.time()
                finish = None
                result = None

                # Put the result behind a try / except so that if we get an error
                # within the method we can still reset the timing status.
                try:
                    result = method(self, *args, **kwargs)
                except Exception:
                    exc_type, exc_value, exc_traceback = sys.exc_info()
                    traceback.print_exception(exc_type, exc_value, exc_traceback)
                    self.__timingstatus__[method.__name__] = False
                    return False

                finish = time.time()

                sys.stdout.write('Instance method \'%s\' of BuilderModule class'
                    ' took %0.3fs to execute.\n' %(method.__name__, (finish - start)))

                # Reset the timing status.
                self.__timingstatus__[method.__name__] = False
                return result

        return __wrapper


    def __new__(cls, name, bases, attrs):
        # Create the __timingstatus__ dictionary that helps stop timers being
        # triggered by inherited methods.
        attrs['__timingstatus__'] = dict()

        for attr in ['__init__', 'run']:
            attrs['__timingstatus__'][attr] = False

            if not attr in attrs:
                continue

            attrs[attr] = cls.time_method(attrs[attr])

        return super(MetaBuilderModule, cls).__new__(cls, name, bases, attrs)

As you can see I have added the @functools.wraps decorator to the __wrapper method so that at least I get the proper method name, but I still don't get the proper arguments.

Example:

 |  Methods defined here:
 |  
 |    __init__(self, *args, **kwargs)

I've seen some articles suggesting monkey patching inspect.getargspec but I can't see this being a practical solution.

Anyone have any other black magic they could suggest?

Cheers,

CB

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文