用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
微信公衆號:獨狼股票分析