【问题标题】:Python : Using Decorators to write Logs on a filePython:使用装饰器在文件上写入日志
【发布时间】:2021-05-03 00:50:12
【问题描述】:

我正在尝试使用 python 装饰器在文件上编写日志,当我在一种方法上使用它时它可以工作,但是一旦我开始尝试在多种方法上使用它,事情就开始变得混乱。

例如,如果我有 2 个日志用于 2 个方法 A() 和 B(),则 B() 在 A() 内部被调用,一个用于我调用它时,一个用于我结束它时事情是这样的:A1 B1 B2 A2 B1 B2 B1 B2

A1 到 A2 很好,但之后 B() 被调用 x 次(它被调用的次数显然发生了变化),我不知道为什么。

这是我的装饰器:

class LogDecorator(object):
    state: str

    def __init__(self, state):
        self.state = state
        self.log_file = 'log.txt'

    def __call__(self, *function):
        if len(function) >= 1:
            def wrapper(params=None):
                if self.state == 'main':
                    self.reset_log_file()
                function_name = function[0].__name__
                self.append_log_to_file('Calling function ' + function_name + '...')
                result = function[0]() if params is None else function[0](params)
                self.append_log_to_file('Function ' + function_name + ' ended. Returned ' + str(result))
                return result
            return wrapper

    def __get__(self, obj, objtype):
        return functools.partial(self.__call__, obj)

    def append_log_to_file(self, message: str) -> None:
        log_file = open(self.log_file, 'a')
        log_file.write(message)
        log_file.close()

    def reset_log_file(self):
        log_file = open(self.log_file, 'w+')
        log_file.write('')
        log_file.close()

我使用“主”状态,因为我在 API 的端点上,我想为每个 API 调用重置文件。

这是我的第一堂主要状态

class AppService:
    @staticmethod
    @LogDecorator(state='main')
    def endpoint() -> Response:
        response: Response = Response()

        response.append_message('Getting all tests')
        tests: list = TestDAO.get_all()
        return response

这是我的第二节课

class TestDAO(BaseDAO):
    @staticmethod
    @LogDecorator(state='sub')
    def get_all() -> list:
        return db.session.query(Test).all()

此示例中的预期输出为

Calling function endpoint...
Calling function get_all...
Function get_all ended. Returned [Objects]
Function endpoint ended. Returned {Object}

但我得到了

Calling function endpoint...
Calling function get_all...
Function get_all ended. Returned [Objects]
Calling function get_all...
Function get_all ended. Returned [Objects]
Calling function get_all...
Function get_all ended. Returned [Objects]
Function endpoint ended. Returned {Object}
Calling function get_all...
Function get_all ended. Returned [Objects]
Calling function get_all...
Function get_all ended. Returned [Objects]
Calling function get_all...
Function get_all ended. Returned [Objects]
Calling function get_all...
Function get_all ended. Returned [Objects]
Calling function get_all...
Function get_all ended. Returned [Objects]
Calling function get_all...
Function get_all ended. Returned [Objects]

谁能弄清楚装饰器为什么会这样?

提前谢谢你

【问题讨论】:

  • 如果您能添加一个示例如何使用装饰器以及该代码的预期和观察输出,那就太好了。
  • 您好,感谢您的反馈,我刚刚做到了 :)

标签: python python-3.x python-decorators


【解决方案1】:

让我们期待以下示例的输出。

def decorator(f):
    def g():
        print('Hello, G.')
    return g


@decorator
def f():
    print('Hello, F.')


f()

它会打印出来

Hello, G.

装饰器根本没有装饰f,而是没有对f进行任何装饰,它返回一个全新的方法(定义为g)。或者,装饰器也可以返回匿名方法。

def decorator(f):
    return lambda : print('Hello, G.')

装饰器所做的就是这个。它接受一个方法(必要时带有参数)并可能使用给定的方法定义一个新方法,也就是装饰。然后它返回新定义的方法,但与给定函数的名称相同。以下抽象会有所帮助。

@decorator
def f():
    print('Hello, F.')

vvvvvvvvvvvvvvvvvvvvvv

def f():  # the name is not changed
#def g():   as if anonymous function
    print('Hello, G.')

看起来装饰 f,然而,它是一个方法,只是命名为f。如果你从AppService 调用TestDAO.get_all,你调用已经decorated TestDAO.get_all

【讨论】:

    【解决方案2】:

    显然我的问题是在调试模式下,当我“观察”作为函数的变量的值时,该函数再次运行。

    删除断点后问题就解决了。

    【讨论】:

      猜你喜欢
      • 2021-04-27
      • 2010-12-11
      • 2011-10-30
      • 1970-01-01
      • 2020-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      相关资源
      最近更新 更多