偶然间在CSDN上面看到了这个代码,真的是什么回路新奇的代码都有啊
import pprint
import os
import ast
import astunparse
SUFFIX_FILE_NAME = "_con_"
SPLIT_LINE_SHOW = "*" * 30
CONST_DEFINE = """
#define True 1
#define False 0
#define_attr switches.IS_SERVER 1
#define_attr switches.IS_CLIENT 0
"""
class NodeVisitDefine(ast.NodeTransformer):
"""
节点转换器
"""
def __init__(self):
super(NodeVisitDefine, self).__init__()
self.const_define_dict = dict()
self.attr_define_dict = dict()
for one_define in CONST_DEFINE.split("\n"):
one_define = one_define.lstrip()
define_keys = one_define.split(" ")
if define_keys[0] == "#define":
self.const_define_dict[define_keys[1]] = eval(define_keys[2])
if define_keys[0] == "#define_attr":
self.attr_define_dict[tuple(define_keys[1].split("."))] = eval(define_keys[2])
print SPLIT_LINE_SHOW
print "computer const dict:"
pprint.pprint(self.const_define_dict)
print SPLIT_LINE_SHOW
print "computer attr dict:"
pprint.pprint(self.attr_define_dict)
print SPLIT_LINE_SHOW
def generic_visit(self, node):
super(NodeVisitDefine, self).generic_visit(node)
if type(node) is ast.Name:
if type(node.ctx) is ast.Load: # 加载变量
if node.id in self.const_define_dict:
define_val = self.const_define_dict[node.id]
if isinstance(define_val, basestring):
return ast.Str(s=define_val)
elif isinstance(define_val, (int, float)):
return ast.Num(n=define_val)
if type(node) is ast.Attribute:
print ast.dump(node)
attr_list = list()
attr_list.append(node.attr)
tmp_node = node
while type(tmp_node.value) is ast.Attribute:
tmp_node = tmp_node.value
attr_list.append(tmp_node.attr)
else:
if type(tmp_node.value) is ast.Name:
attr_list.append(tmp_node.value.id)
attr_list.reverse()
if tuple(attr_list) in self.attr_define_dict:
define_val = self.attr_define_dict[tuple(attr_list)]
if isinstance(define_val, basestring):
return ast.Str(s=define_val)
elif isinstance(define_val, (int, float)):
return ast.Num(n=define_val)
return node
def convert_one_file(dir_name, file_name):
"""
转换一个文件
:param dir_name:
:param file_name:
:return:
"""
if file_name.split(".")[0][-len(SUFFIX_FILE_NAME):len(file_name)] == SUFFIX_FILE_NAME:
print "skip file:%s ..." % file_name
return
print "convert file: %s ...." % file_name
ori_file = "%s%s%s" % (dir_name, os.sep, file_name)
with open(ori_file, "r") as ff:
src = ff.read()
ast_node = ast.parse(src, file_name)
if ast_node is None:
print "convert file:%s failed!" % file_name
return
con_file_name = "%s%s.py" % (file_name.split(".")[0], SUFFIX_FILE_NAME)
new_file = "%s%s%s" % (dir_name, os.sep, con_file_name)
if os.path.exists(new_file):
os.remove(new_file)
with open(new_file, "w") as ff:
con_node = NODE_CONVERTER.visit(ast_node)
astunparse.Unparser(con_node, ff)
def convert_one_dir(dir_name):
"""
转换一个目录
:param dir_name:
:return:
"""
for dir_path, _, file_names in os.walk(dir_name): # 遍历文件
print "convert dir: %s ....\n" % dir_path
for file_name in file_names:
convert_one_file(dir_path, file_name)
NODE_CONVERTER = NodeVisitDefine()
if __name__ == "__main__":
dir_split = os.sep # 路径分隔符
con_files_dir = [
"./opt_module"
] # 需要转换文件的路径
for one_dir in con_files_dir:
one_dir = one_dir.replace("/", dir_split)
convert_one_dir(one_dir)
通过Ast模块的替换节点功能
在 CONST_DEFINE 变量中定义需要替换的 常量 和 属性定义,可以避免python运行期求值减慢速度。
传入需要处理的包的目录路径,即可输出转换后的文件。
原文地址连接https://blog.csdn.net/weixin_42092782/article/details/84899772
个人想法:
可以利用python自带的 “True” : “Ture” 的方式创建更多的,这样就是一个符合python语法的【宏定义了】
0 条评论