python 获取py文件中的函数和类,所在位置和层级关系导出为json格式

读取结果

在这里插入图片描述

代码

#  _*_ coding:utf-8 _*_
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:
        """
        # 获取 func_set 中所有的函数位置
        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')
                # 如果当前 node.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)


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值