创建日志记录 Class 包装器
Creating a Logging Class Wrapper
我正在尝试编写一个快速装饰器来管理各种功能的日志记录 returns。我不是很精通装饰器,所以你能提供的任何帮助都会很有帮助!
from functools import update_wrapper
from typing import Any, Optional
from logging import getLogger
from time import perf_counter
from datetime import datetime
class logger:
def __init__(self, func:callable, response:str = "debug"):
self.logger = getLogger()
self.func = func
self.response = response
update_wrapper(self, func)
def __call__(self, *args, **kwargs):
return getattr(self, self.response)
def debug(self, *args, **kwargs):
self.logger.debug(f"Running {__name__} with id: {id(self)} at {datetime.now()}")
start = perf_counter()
value = self.func(*args, **kwargs)
end = perf_counter()
self.logger.debug(f"""Completed {__name__} with id: {id(self)} at {datetime.now()}.
Total Time to run: {end - start:.6f}s""")
return value
def info(self, *args, **kwargs):
self.logger.info(f"Running {__name__} at {datetime.now()}.")
return self.func(*args, **kwargs)
@logger(response="debug")
def stuff(x):
return x*x
stuff(2)
我收到的错误是:
TypeError: __init__() missing 1 required positional argument: 'func'
,
很明显,它不喜欢所需的可调用对象和响应要求。但是,我在所有其他基于 class 的装饰器设置中看到 func 需要作为 __init__
的一部分被调用,而且我还看到您可以传递装饰器附加信息。我在这里做错了什么?
编辑:
getattr(self, self.response)
的目的是让 __call__
返回的函数是 debug
或 info
日志记录的函数。这允许我利用装饰器@logging 进行日志记录和调试,但根据装饰器中指定的响应值(即@logging(response="info"))产生两个不同的结果。
解决方案:
class logger:
def __init__(self, response:str = "debug"):
self.logger = getLogger()
self.response = response
def __call__(self, func:callable):
update_wrapper(self, func)
self.func = func
return getattr(self, self.response)
def debug(self, *args, **kwargs):
self.logger.debug(f"Running {self.func.__name__} (type:{type(self.func)}) with id: {id(self)} at {datetime.now()}")
start = perf_counter()
value = self.func(*args, **kwargs)
end = perf_counter()
self.logger.debug(f"""Completed {self.func.__name__} with id: {id(self)} at {datetime.now()}.
Total Time to run: {end - start:.6f}s""")
return value
def info(self, *args, **kwargs):
self.logger.info(f"Running {self.func.__name__} at {datetime.now()}.")
return self.func(*args, **kwargs)
我不知道您的代码应该做什么,尤其是(对我而言)不清楚应该将哪种参数传递给 getattr(self, self.response)(*args, **kwargs)
。我这么说是为了了解装饰器的正确工作流程。
所以你的代码永远不会工作。这里有一些可能的装饰示例:
__call__
方式:@logger(response="debug")
class logger_1:
def __init__(self, response:str = "debug"):
print(response)
def __call__(self, func):
self.func = func
return self # ? depends on what are you doing
def debug(self, *args, **kwargs):
# ...
def info(self, *args, **kwargs):
#...
@logger_1(response="debug")
def stuff(x):
return x*x
更“抽象”的层次:@logger(response="debug").('some_parameter').debug_method
class logger_2:
def __init__(self, response:str = "debug"):
print(response)
def __call__(self, *args, **kwargs):
self.updated_response = getattr(self, self.response)(*args, **kwargs) # just an example
return self
def debug_method(self, func):
self.func = func
# ...
return func
def debug(self, *args, **kwargs):
# ...
def info(self, *args, **kwargs):
#...
@logger_2(response="debug")('some_parameter').debug_method
def stuff(x):
return x*x
注意: logger_2(response="debug").('some_parameter').debug_method
没有接受参数,因为它等待目标函数 stuff
的“馈送”
这些是约束工作流的语法示例,因此在设计装饰器时需要小心
我正在尝试编写一个快速装饰器来管理各种功能的日志记录 returns。我不是很精通装饰器,所以你能提供的任何帮助都会很有帮助!
from functools import update_wrapper
from typing import Any, Optional
from logging import getLogger
from time import perf_counter
from datetime import datetime
class logger:
def __init__(self, func:callable, response:str = "debug"):
self.logger = getLogger()
self.func = func
self.response = response
update_wrapper(self, func)
def __call__(self, *args, **kwargs):
return getattr(self, self.response)
def debug(self, *args, **kwargs):
self.logger.debug(f"Running {__name__} with id: {id(self)} at {datetime.now()}")
start = perf_counter()
value = self.func(*args, **kwargs)
end = perf_counter()
self.logger.debug(f"""Completed {__name__} with id: {id(self)} at {datetime.now()}.
Total Time to run: {end - start:.6f}s""")
return value
def info(self, *args, **kwargs):
self.logger.info(f"Running {__name__} at {datetime.now()}.")
return self.func(*args, **kwargs)
@logger(response="debug")
def stuff(x):
return x*x
stuff(2)
我收到的错误是:
TypeError: __init__() missing 1 required positional argument: 'func'
,
很明显,它不喜欢所需的可调用对象和响应要求。但是,我在所有其他基于 class 的装饰器设置中看到 func 需要作为 __init__
的一部分被调用,而且我还看到您可以传递装饰器附加信息。我在这里做错了什么?
编辑:
getattr(self, self.response)
的目的是让 __call__
返回的函数是 debug
或 info
日志记录的函数。这允许我利用装饰器@logging 进行日志记录和调试,但根据装饰器中指定的响应值(即@logging(response="info"))产生两个不同的结果。
解决方案:
class logger:
def __init__(self, response:str = "debug"):
self.logger = getLogger()
self.response = response
def __call__(self, func:callable):
update_wrapper(self, func)
self.func = func
return getattr(self, self.response)
def debug(self, *args, **kwargs):
self.logger.debug(f"Running {self.func.__name__} (type:{type(self.func)}) with id: {id(self)} at {datetime.now()}")
start = perf_counter()
value = self.func(*args, **kwargs)
end = perf_counter()
self.logger.debug(f"""Completed {self.func.__name__} with id: {id(self)} at {datetime.now()}.
Total Time to run: {end - start:.6f}s""")
return value
def info(self, *args, **kwargs):
self.logger.info(f"Running {self.func.__name__} at {datetime.now()}.")
return self.func(*args, **kwargs)
我不知道您的代码应该做什么,尤其是(对我而言)不清楚应该将哪种参数传递给 getattr(self, self.response)(*args, **kwargs)
。我这么说是为了了解装饰器的正确工作流程。
所以你的代码永远不会工作。这里有一些可能的装饰示例:
__call__
方式:@logger(response="debug")
class logger_1:
def __init__(self, response:str = "debug"):
print(response)
def __call__(self, func):
self.func = func
return self # ? depends on what are you doing
def debug(self, *args, **kwargs):
# ...
def info(self, *args, **kwargs):
#...
@logger_1(response="debug")
def stuff(x):
return x*x
更“抽象”的层次:@logger(response="debug").('some_parameter').debug_method
class logger_2:
def __init__(self, response:str = "debug"):
print(response)
def __call__(self, *args, **kwargs):
self.updated_response = getattr(self, self.response)(*args, **kwargs) # just an example
return self
def debug_method(self, func):
self.func = func
# ...
return func
def debug(self, *args, **kwargs):
# ...
def info(self, *args, **kwargs):
#...
@logger_2(response="debug")('some_parameter').debug_method
def stuff(x):
return x*x
注意: logger_2(response="debug").('some_parameter').debug_method
没有接受参数,因为它等待目标函数 stuff
这些是约束工作流的语法示例,因此在设计装饰器时需要小心