Home Page
Search
\begin{md} # 符号表可视化 看 cpython 代码的过程中经常需要验证符号的一些作用域,属性等,通过修改源码 print 或者用 symtable 模块分析比较麻烦, 所以开发了这个工具用来分析嵌套的符号表和符号表中符号的属性等。 ## 代码 ```python import os import sys import symtable import prettytable def print_symtable(st_info:list): head = ["name", "global", "nonlocal", "local", "free", "param", "referenced", "imported"] tb = prettytable.PrettyTable(head) for sym in st_info: row = [ sym.get("name", ""), sym.get("is_global", ""), sym.get("is_nonlocal", ""), sym.get("is_local", ""), sym.get("is_free", ""), sym.get("is_param", ""), sym.get("is_referenced", ""), sym.get("is_imported", ""), ] tb.add_row(row) print(tb) def analysis_symtable(st:symtable.SymbolTable, st_name:str): if not st_name: st_name = st.get_name() else: st_name = "{}.{}".format(st_name, st.get_name()) print("\nSymbol Table: ", st_name) st_info = [] for symbol in st.get_symbols(): info = { "name" : symbol.get_name() or "", "is_global" : symbol.is_global() or "", "is_nonlocal" : symbol.is_nonlocal() or "", "is_local" : symbol.is_local() or "", "is_free" : symbol.is_free() or "", "is_param" : symbol.is_parameter() or "", "is_referenced" : symbol.is_referenced() or "", "is_imported" : symbol.is_imported() or "", } st_info.append(info) print_symtable(st_info) for child in st.get_children(): analysis_symtable(child, st_name) def print_symtable_tree(st:symtable.SymbolTable, depth=0, need_draw=[]): if depth == 0: print("\nSymbol Table Tree\n") print(st.get_name()) print("│") if len(st.get_children()) > 0: need_draw.append(depth) for idx, child in enumerate(st.get_children()): if idx == len(st.get_children())-1: need_draw.pop() for i in range(depth): if i in need_draw: print("│ ", end="") else: print(" ", end="") if idx == len(st.get_children()) -1: print("└──", child.get_name()) else: print("│──", child.get_name()) print_symtable_tree(child, depth+1) if depth == 0: print() def get_symtable(path:str): with open(path, "r") as f: code = "".join(f.readlines()) st = symtable.symtable(code, path, "exec") return st if __name__ == "__main__": if len(sys.argv) <= 1: print("usage: python print_symtable.py python_script_name") exit(0) path = sys.argv[1] if not os.path.exists(path): print("{} not exists".format(path)) exit(0) st = get_symtable(path) analysis_symtable(st, "") print_symtable_tree(st) ``` 使用这个插件需要安装 `prettytable` 包。 ## 用法 以标准库中的 `Lib/abc.py` 模块为例进行分析。 ```bash $ python3 ./learn/tools/print_symtable.py Lib/abc.py Symbol Table: top +------------------------+--------+----------+-------+------+-------+------------+----------+ | name | global | nonlocal | local | free | param | referenced | imported | +------------------------+--------+----------+-------+------+-------+------------+----------+ | abstractmethod | True | | True | | | | | | abstractclassmethod | True | | True | | | | | | classmethod | True | | | | | True | | | abstractstaticmethod | True | | True | | | | | | staticmethod | True | | | | | True | | | abstractproperty | True | | True | | | | | | property | True | | | | | True | | | get_cache_token | True | | True | | | | True | | _abc_init | True | | True | | | | True | | _abc_register | True | | True | | | | True | | _abc_instancecheck | True | | True | | | | True | | _abc_subclasscheck | True | | True | | | | True | | _get_dump | True | | True | | | | True | | _reset_registry | True | | True | | | | True | | _reset_caches | True | | True | | | | True | | ABCMeta | True | | True | | | True | True | | type | True | | | | | True | | | ImportError | True | | | | | True | | | update_abstractmethods | True | | True | | | | | | ABC | True | | True | | | | | +------------------------+--------+----------+-------+------+-------+------------+----------+ Symbol Table: top.abstractmethod +---------+--------+----------+-------+------+-------+------------+----------+ | name | global | nonlocal | local | free | param | referenced | imported | +---------+--------+----------+-------+------+-------+------------+----------+ | funcobj | | | True | | True | True | | +---------+--------+----------+-------+------+-------+------------+----------+ Symbol Table: top.abstractclassmethod +----------------------+--------+----------+-------+------+-------+------------+----------+ | name | global | nonlocal | local | free | param | referenced | imported | +----------------------+--------+----------+-------+------+-------+------------+----------+ | __isabstractmethod__ | | | True | | | | | | __init__ | | | True | | | | | +----------------------+--------+----------+-------+------+-------+------------+----------+ Symbol Table: top.abstractclassmethod.__init__ +-----------+--------+----------+-------+------+-------+------------+----------+ | name | global | nonlocal | local | free | param | referenced | imported | +-----------+--------+----------+-------+------+-------+------------+----------+ | self | | | True | | True | | | | callable | | | True | | True | True | | | super | True | | | | | True | | | __class__ | | | | True | | True | | +-----------+--------+----------+-------+------+-------+------------+----------+ # 省略... Symbol Table Tree top │ │── abstractmethod │── abstractclassmethod │ └── __init__ │── abstractstaticmethod │ └── __init__ │── abstractproperty │── ABCMeta │ │── __new__ │ │── register │ │── __instancecheck__ │ │── __subclasscheck__ │ │── _dump_registry │ │── _abc_registry_clear │ └── _abc_caches_clear │── update_abstractmethods └── ABC ``` \end{md}
Home Page