在 Python 中拦截方法调用

Posted

技术标签:

【中文标题】在 Python 中拦截方法调用【英文标题】:Intercept method calls in Python 【发布时间】:2021-06-07 17:01:29 【问题描述】:

我正在用 python 实现一个 RESTful Web 服务,并想通过拦截函数调用并记录它们的执行时间等来添加一些 QOS 日志记录功能。

基本上我想到了一个所有其他服务都可以继承的类,它会自动覆盖默认方法实现并将它们包装在一个记录器函数中。实现这一目标的最佳方法是什么?

【问题讨论】:

【参考方案1】:

如果你为每个函数写一个装饰器会怎样?这是python's wiki 的示例。

您是否使用任何网络框架来提供您的网络服务?还是你手工做所有事情?

【讨论】:

这是一个例子,了解它是如何工作的。根据定义,示例并不是什么神奇的东西【参考方案2】:

这样的?这隐含地为您的方法添加了一个装饰器(如果您愿意,也可以基于此创建一个显式装饰器):

class Foo(object):
    def __getattribute__(self,name):
        attr = object.__getattribute__(self, name)
        if hasattr(attr, '__call__'):
            def newfunc(*args, **kwargs):
                print('before calling %s' %attr.__name__)
                result = attr(*args, **kwargs)
                print('done calling %s' %attr.__name__)
                return result
            return newfunc
        else:
            return attr

当你现在尝试类似:

class Bar(Foo):
    def myFunc(self, data):
        print("myFunc: %s"% data)

bar = Bar()
bar.myFunc(5)

你会得到:

before calling myFunc
myFunc:  5
done calling myFunc

【讨论】:

不应该是 retval = attr(*args, **kwargs) ... return retval 以防方法返回什么? 如果Foo 不直接从object 继承,那么您可能需要调用super(Foo, self).__getattribute__ 而不是object.__getattribute__,以便尊重继承链。 @FlorianBrucker:使用super 并正确理解 MRO 充其量是棘手的,我更喜欢提供显式基类,当然在这样的示例中。 @KillianDS 我坚决支持 FlorianBrucker 在这一点上,object.__getattribute__ 不是 pythonic 并且会增加混乱。 @Jay 它有什么非pythonic? “显式优于隐式”呢?

以上是关于在 Python 中拦截方法调用的主要内容,如果未能解决你的问题,请参考以下文章

Spring AOP不拦截从对象内部调用的方法

Spring AOP不拦截从对象内部调用的方法原因

Spring AOP不拦截从对象内部调用的方法原因

Spring AOP不拦截从对象内部调用的方法原因

Spring AOP 是不是可以拦截 线程内部调用的拦截方法?

Ninject拦截:服务调用被拦截的方法在自身内部调用时未被拦截