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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章