读取结果
代码
import ast
import os
from jsonpath import jsonpath
class ReadPyFunc():
"""获取 py 文件中所有的函数"""
def __init__(self, ):
self.func_set = {}
@staticmethod
def get_py(file_path: str):
"""
获取py文件对象
:param file_path: 文件路径
:return:
"""
with open(file_path, "r", encoding='utf-8') as f:
ast_py = ast.parse(f.read())
return ast_py
@staticmethod
def get_path_value(dict_obj: dict, path: list):
"""根据路径获取值,或键dict对象"""
for k in path:
dict_obj = dict_obj[k]
return dict_obj
def __search_func_loc(self, func_set: dict, curr_func: dict):
"""
找到函数的位置
:param func_set: 已读取的文件函数信息
:param curr_func:
:return:
"""
fs_lineno_list = jsonpath(func_set, '$..lineno')
fs_lineno_path = jsonpath(func_set, '$..lineno', result_type='IPATH')
fs_end_lineno_list, fs_lineno_obj = [], []
for p in fs_lineno_path:
p.pop()
dict_x_obj = self.get_path_value(func_set, p)
fs_end_lineno_list.append(dict_x_obj['end_lineno'])
fs_lineno_obj.append(dict_x_obj)
sorted_lineno = sorted(fs_lineno_list)
for index, lineno in enumerate(sorted_lineno):
if curr_func['lineno'] < lineno:
func_set_lineno = sorted_lineno[index - 1]
break
else:
func_set_lineno = sorted_lineno[-1]
func_set_list = list(zip(fs_lineno_list, fs_end_lineno_list, fs_lineno_path, fs_lineno_obj))
for lineno, end_lineno, path, obj in func_set_list:
if func_set_lineno == lineno:
if curr_func['end_lineno'] <= end_lineno:
return obj['func']
else:
path.pop()
return self.get_path_value(self.func_set, path)
def get_py_func(self, file_path: str):
"""获取 py 文件中所有的类和函数层级和行"""
ast_py = self.get_py(file_path)
for node in ast.walk(ast_py):
if isinstance(node, ast.ClassDef) or isinstance(node, ast.FunctionDef):
curr_func = {
'type': 'ClassDef' if isinstance(node, ast.ClassDef) else 'FunctionDef',
'lineno': node.lineno,
'end_lineno': node.end_lineno,
'func': {}
}
end_lineno_list = jsonpath(self.func_set, '$..end_lineno')
line = max(end_lineno_list) if end_lineno_list else 0
if node.lineno > line:
self.func_set[node.name] = curr_func
else:
scl = self.__search_func_loc(self.func_set, curr_func)
scl[node.name] = curr_func
return self.func_set
if __name__ == '__main__':
ret = ReadPyFunc().get_py_func(r'D:\p5.py')
print(ret)