简单的日志对象

0 投票
3 回答
620 浏览
提问于 2025-04-17 06:23

我有一个 python 模块,这个模块里有一个类叫 ModuleClass,但是我不能修改这个类。

现在,我想对这个类的方法调用进行 代理,并添加一些日志记录的功能。我想这应该通过转发对象和相应的代理来实现 (参考《Effective Java》,第16条)

我想出的 python 伪代码如下。

(抱歉,我的 python 技术真的很差,如果你能指出这里的错误,我会很感激)。

# This is what I've got in my module and this code cannot be changed.
class ModuleClass(object):
    def method1(self):
        # Some implementation
        pass()
    def method2(self):
        # Some implementation
        pass()

# Simple forwarding proxy to avoid the situation described in Effective Java, I16

# However, in Java this class would usually be extending the interface, not
# inheriting 'ModuleClass' (I'm confused and don't know how to do the same
# in python).

class ForwardingModuleClass(ModuleClass):
    # 'proxifiedObject' is 
    def __init__(self, proxifiedObject):
        self.proxifiedObject = proxifiedObject

    # Overriding the first method
    def method1(self):
        return self.proxifiedObject.method1()

    # Same for method2...

class LoggingModuleClass(ForwardingModuleClass):
    # 'classThatActuallyDoesStuff' should be an instance of 'ModuleClass'.
    def __init__(self, classThatActuallyDoesStuff):
        # Sorry for my bad knowledge of python syntax, but
        # I assume I can initialize the superclass here using
        # the supplied 'ModuleClass' instance.
        super(classThatActuallyDoesStuff)

    # Overriding the first method.
    def method1(self):
        print("Yay! This 'method1' really logs something!")
        return super.method1()

    # Overriding the second method.
    def method2(self):
        print("Yay!!!! This 'method2' also does something cool!")
        return super.method2()

现在,我猜如果写得正确,这段代码应该能工作,并且我会有一个用于我的初始 ModuleClass 的日志代理。

如果有错误,或者这段代码不符合 python 的风格,请指出来。

另外,我怀疑这可以很容易地通过 decorators 来实现, 但不幸的是,我不知道该怎么做,也不知道如果 ModuleClass 已经有一些方法装饰器会发生什么。

你能在这方面帮我吗?

3 个回答

1

如果你在寻找装饰器的解决方案,可以看看这个帖子里的回答:Python 装饰器让函数忘记它属于一个类

你提到想要避免“多余的信息”(比如 method1 调用 method2 的时候),那么我建议你选择 Cat Plus Plus 提供的解决方案,否则我会推荐使用运算符。

2

直接继承ModuleClass怎么样:

import logging

logger=logging.getLogger(__name__)

class LoggingModuleClass(ModuleClass):
    def method1(self):
        logger.info("Yay! This 'method1' really logs something!")
        return super(LoggingModuleClass,self).method1()
    def method2(self):
        logger.info("Yay! This 'method2' also does something cool!")
        return super(LoggingModuleClass,self).method2()

logging.basicConfig(level=logging.DEBUG)

(我加了一些代码,展示了如何用Python的方式进行基本的日志记录设置。)

2

如果你真的想要一个包装器,那就直接写一个,不需要继承其他类或者中间类。

class LoggingFoo(object):
    def __init__(self, *args, **kwargs):
        self.obj = Foo(*args, **kwargs)

    def method1(self):
        # ...
        return self.obj.method1()

    def method2(self):
        # ...
        return self.obj.method2()

撰写回答