
本文详解如何修正因装饰器参数传递错误导致的 TypeError,通过静态方法+闭包结构构建可接收配置参数(如 file_path)的装饰器工厂,确保 @Logger.catch(file_path=...) 语法正常工作。
本文详解如何修正因装饰器参数传递错误导致的 `typeerror`,通过静态方法+闭包结构构建可接收配置参数(如 `file_path`)的装饰器工厂,确保 `@logger.catch(file_path=...)` 语法正常工作。
在 Python 中,当希望装饰器支持自定义参数(例如 @Logger.catch(file_path='log.txt')),它本质上是一个装饰器工厂(decorator factory):先调用工厂函数传入配置,再返回真正的装饰器函数。而原代码中 catch 被定义为普通实例方法(隐含 self 参数),又未正确处理 func 的传入时机,导致解释器误将 'tests/example.log' 当作 func,从而抛出 missing 1 required positional argument: 'func' 错误。
正确做法是将 catch 声明为 @staticmethod,使其脱离实例绑定,并采用三层嵌套结构:
- 第一层:接收装饰器配置参数(如 file_path);
- 第二层:接收被装饰的函数 func,返回包装器;
- 第三层:wrapper 执行实际逻辑(try/except + 日志记录)。
以下是修复后的完整实现示例:
import sys
import traceback
class Logger:
@staticmethod
def catch(file_path=None):
def decorator(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
_, _, tb = sys.exc_info()
traceback_info = traceback.extract_tb(tb)
if traceback_info:
last_frame = traceback_info[-1]
line = last_frame[1]
file = last_frame[0]
function_name = last_frame[2]
else:
line = file = function_name = "?"
# 假设 Logger.error 已正确定义(需自行实现)
Logger.error(
log_msg=str(e),
highlighting=True,
print_out=True,
line=[line, file, function_name],
file_path=file_path
)
raise # 重新抛出异常,避免静默吞掉错误
return wrapper
return decorator
@staticmethod
def error(log_msg, highlighting, print_out, line, file_path=None):
# 示例:简单控制台输出 + 可选文件写入
msg = f"[ERROR] {log_msg} | File: {line[1]}, Line: {line[0]}, Func: {line[2]}"
if print_out:
print(msg)
if file_path:
try:
with open(file_path, "a") as f:
f.write(msg + "\n")
except OSError as write_err:
print(f"[WARN] Failed to write log to {file_path}: {write_err}")
✅ 使用方式保持不变,且完全符合预期:
@Logger.catch(file_path='tests/example.log')
def example_function():
var1 = 5
var = 0
result = var1 / var # 触发 ZeroDivisionError
print(result)
⚠️ 注意事项:
- @staticmethod 是关键——若使用 @classmethod 或普通方法,func 会与 self/cls 冲突;
- wrapper 中建议 raise 原始异常(除非明确需要静默处理),否则调用链将中断;
- traceback.extract_tb(tb) 返回列表可能为空,务必做边界检查(如上示例);
- Logger.error 需独立实现并确保线程安全(如多线程场景下推荐使用 threading.Lock 或 logging 模块替代自定义方案)。
通过该模式,你不仅能解决当前崩溃问题,还可轻松扩展其他参数(如 level='WARNING'、include_stack=True 等),构建灵活、可复用的日志装饰器体系。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











