78 lines
2.5 KiB
Python
78 lines
2.5 KiB
Python
import inspect
|
|
import itertools
|
|
from pathlib import Path
|
|
from types import FrameType
|
|
|
|
from mower.utils.path import get_path
|
|
|
|
|
|
# https://stackoverflow.com/a/78770438
|
|
def fast_stack(max_depth: int | None = None):
|
|
def frame_infos(frame: FrameType | None):
|
|
while frame := frame and frame.f_back:
|
|
yield inspect.FrameInfo(
|
|
frame,
|
|
inspect.getfile(frame),
|
|
frame.f_lineno,
|
|
frame.f_code.co_name,
|
|
None,
|
|
None,
|
|
)
|
|
|
|
return list(itertools.islice(frame_infos(inspect.currentframe()), max_depth))
|
|
|
|
|
|
def caller_info():
|
|
caller = fast_stack(3)[2]
|
|
relative_path = Path(caller.filename)
|
|
try:
|
|
relative_path = relative_path.relative_to(get_path("@install"))
|
|
except ValueError:
|
|
pass
|
|
return f"{relative_path}:{caller.lineno}"
|
|
|
|
|
|
def log_info():
|
|
"""日志前缀
|
|
|
|
利用调用栈的信息找出打印日志的代码来自哪里。
|
|
|
|
类名的获取:
|
|
1. 如果类存在solver_name属性,返回这个Solver的名字。如果solver_name为None,使用qualname替代;
|
|
2. 如果没有被Solver调用,返回调用栈最内层的类。
|
|
"""
|
|
|
|
# 遍历调用栈,记录最内层的类,并寻找Solver类。找到Solver类后返回;没有Solver类则返回最内层的类。
|
|
caller_class = None # 记录最内层的类
|
|
stack_info = fast_stack()
|
|
func_name = stack_info[2].function
|
|
lineno = stack_info[2].lineno
|
|
relative_path = Path(stack_info[2].filename)
|
|
try:
|
|
relative_path = relative_path.relative_to(get_path("@install"))
|
|
except ValueError:
|
|
pass
|
|
for st in stack_info[2:]:
|
|
try:
|
|
caller = st.frame.f_locals["self"].__class__ # 不是类的会触发异常
|
|
qualname = caller.__qualname__
|
|
if caller_class is None: # 更新最内层的类
|
|
caller_class = qualname
|
|
name = caller.solver_name # 不是Solver的类会触发异常
|
|
|
|
return name or qualname, relative_path, func_name, lineno
|
|
except Exception:
|
|
pass
|
|
return caller_class, relative_path, func_name, lineno
|
|
|
|
|
|
def log_debug():
|
|
stack_info = fast_stack(3)[2]
|
|
func_name = stack_info.function
|
|
lineno = stack_info.lineno
|
|
relative_path = Path(stack_info.filename)
|
|
try:
|
|
relative_path = relative_path.relative_to(get_path("@install"))
|
|
except ValueError:
|
|
pass
|
|
return relative_path, func_name, lineno
|