用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
微信公众号:独狼股票分析