用Tkinter打造GUI开发工具(20)用ast模块分析代码

用Tkinter打造GUI开发工具(20)用ast模块分析代码


我们在开发Python的GUI开发工具,首先要实现对Python程序代码分析。因此我首先考虑到使用ast模块。ast(Abstract Syntax Trees)是python中非常有用的一个模块,我们可以通过分析python的抽象语法树来对python的代码进行分析和修改。
一、 获取语法树
ast模块的基本使用是非常简单的,我们可以通过如下代码快速得到一棵抽象语法树:

import ast
py_root = ast.parse("print(\'hello Python !\')")

从上面程序我们可以看出,输入的是文本Python代码。

二、读入一个Python的py文件

    def readtext(filename):   #读入文本文件
        ss=''
        with open(filename,encoding='utf-8') as f:
            s=f.read()
            ss=ss+s
        return ss

三、根据Python程序构造语法树
根据Python程序构造语法树,从语法树中获取库名,类名,函数名和变量名,分别存放到字典中。字典key为名称,值为定义时所对应的行号。

global lib_dict   #库列字典
global var_dict   #变量字典
global func_dict  #函数字典
global class_dict  #类字典
lib_dict={}
var_dict={}
func_dict={}
class_dict={}

class ParseTree(ast.NodeVisitor):

    def generic_visit(self, node):
        ast.NodeVisitor.generic_visit(self, node)
        
    def visit_ClassDef(self, node):
        class_dict[node.name]=[node.lineno]
        ast.NodeVisitor.generic_visit(self, node)
        
    def visit_ImportFrom(self, node):
        try:
            lib_dict[node.module]=[node.lineno]
            ast.NodeVisitor.generic_visit(self, node)
        except Exception as e:
            pass
        
    def visit_FunctionDef(self, node):
        func_dict[node.name]=[node.lineno]


    def visit_Assign(self, node):
        try:

            var_dict[node.targets[0].id]=[node.lineno]
        except Exception as e:
            pass

def MyParse(s):
    global lib_dict   #库列表
    global var_dict   #变量列表
    global func_dict  #函数列表
    global class_dict  #类类表
    lib_dict={}
    var_dict={}
    func_dict={}
    class_dict={}
    py_root = ast.parse(s)
    pt = ParseTree()
    pt.visit(py_root)
    return py_root

下面给出Python3.7中全部的程序代码,假定文件名为:py010a.py:

import ast

global lib_dict   #库字典
global var_dict   #变量字典
global func_dict  #函数字典
global class_dict  #类字典
lib_dict={}
var_dict={}
func_dict={}
class_dict={}

class ParseTree(ast.NodeVisitor):

    def generic_visit(self, node):
        ast.NodeVisitor.generic_visit(self, node)
        
    def visit_ClassDef(self, node):
        class_dict[node.name]=[node.lineno]
        ast.NodeVisitor.generic_visit(self, node)
        
    def visit_ImportFrom(self, node):
        try:
            lib_dict[node.module]=[node.lineno]
            ast.NodeVisitor.generic_visit(self, node)
        except Exception as e:
            pass
        
    def visit_FunctionDef(self, node):
        func_dict[node.name]=[node.lineno]


    def visit_Assign(self, node):
        try:

            var_dict[node.targets[0].id]=[node.lineno]
        except Exception as e:
            pass

def MyParse(s):
    global lib_dict   #库字典
    global var_dict   #变量字典
    global func_dict  #函数字典
    global class_dict  #类字典
    lib_dict={}
    var_dict={}
    func_dict={}
    class_dict={}
    py_root = ast.parse(s)
    pt = ParseTree()
    pt.visit(py_root)
    return py_root


def readtext(filename):   #读入文本文件
    ss=''
    with open(filename,encoding='utf-8') as f:
        s=f.read()
        ss=ss+s
    return ss

py=readtext('py010a.py')   #读取py文件     

py_root=MyParse(py)
print('库',lib_dict)
print('类',class_dict)
print('函数',func_dict)
print('变量',var_dict)

程序运行结果如下:

库 {}
类 {'ParseTree': [12]}
函数 {'generic_visit': [14], 'visit_ClassDef': [17], 'visit_ImportFrom': [21], 'visit_FunctionDef': [28], 'visit_Assign': [32], 'MyParse': [39], 'readtext': [54]}
变量 {'lib_dict': [7], 'var_dict': [8], 'func_dict': [9], 'class_dict': [10], 'py': [61], 'py_root': [63]}

我们经过试验发现,ast分析可能不够完整,有时行号不对,比实际行号少几行。
在这里插入图片描述
本人猜测,ast对Python程序进行了分析,忽略了空行。我们删除掉空行测试一下。
在这里插入图片描述
删除空行后,行号基本对应了。还有些问题,作者也不明白,上例明显导入了ast模块,可是分析却没有显示出来。有些又能分析出来,却不够全面。如下图。
在这里插入图片描述
希望清楚地朋友能给我指导一下。

在这里插入图片描述
在这里插入图片描述
上面是正在开发的中文Python教学软件,中英文关键字都能够识别和运行。等完善后,给大家提供。
独狼荷蒲qq:2775205
小白量化群:524949939
微信公众号:独狼股票分析

发布了56 篇原创文章 · 获赞 67 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/hepu8/article/details/97568462