偶然间在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语法的【宏定义了】

分类: PYTHON

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注