python ast 语法分析_怀瑜的博客

文章推薦指數: 80 %
投票人數:10人

ast(Abstract Syntax Trees)是python中非常有用的一个模块,我们可以通过分析python的抽象语法树来对python的代码进行分析和修改。

ast作用在python ... pythonast语法分析 怀瑜 于 2017-02-2018:42:24 发布 32412 收藏 40 分类专栏: python 文章标签: python ast 语法树 编译 版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/ma89481508/article/details/56017697 版权 python 专栏收录该内容 1篇文章 0订阅 订阅专栏 ast(AbstractSyntaxTrees)是python中非常有用的一个模块,我们可以通过分析python的抽象语法树来对python的代码进行分析和修改。

ast作用在python代码的语法被解析后,被编译成字节码之前。

一.ast 1.获取语法树 ast模块的基本使用是非常简单的,我们可以通过如下代码快速得到一棵抽象语法树: importast root_node=ast.parse("print'helloworld'") root_node-><_ast.moduleobjectat0x9e3df6c> 通过ast的parse方法得到asttree的根节点root_node,我看可以通过根节点来遍历语法树,从而对python代码进行分析和修改。

ast.parse(可以直接查看ast模块的源代码)方法实际上是调用内置函数compile进行编译,如下所示: defparse(source,filename='',mode='exec'): """ ParsethesourceintoanASTnode. Equivalenttocompile(source,filename,mode,PyCF_ONLY_AST). """ returncompile(source,filename,mode,PyCF_ONLY_AST) 传递给compile特殊的flag=PyCF_ONLY_AST,来通过compile返回抽象语法树。

(关于compile的第四个参数flag有时间可以深入研究下) 2.节点类型分析 语法树中的每个节点都对应ast下的一种类型,根节点是ast.Moudle类型,在分析的时候可以通过isinstance函数方便的进行节点类型的判断。

ast中存在的节点的所有类型可以参考:ast节点类型比如a=10这样一条语句对应ast.Assign节点类型,而Assign节点类型分别有两个子节点,分别为ast.Name类型的a和ast.Num类型的10等。

我们可以通过ast.dump(node)函数来将node格式化,并进行打印,以查看节点内容,以“a=10”这行代码为例。

Module(body=[Assign(targets=[Name(id='a',ctx=Store())],value=Num(n=10))]) (1)root节点 Module(body=[Assign(targets=[Name(id='a',ctx=Store())],value=Num(n=10))])root节点是Module类型,由于只有一行代码,所有root节点只有Assign这样一个子节点。

(2)子节点 Assign(targets=[Name(id='a',ctx=Store())],value=Num(n=10))上述的Assign节点有三个子节点,分别是Name,Store和Num.Name(id='a',ctx=Store())Num(n=10)而Name有一个子节点,Store.Store()(Store表示Name中操作时赋值,类型的有Load,del,具体参考节点类型的文档)一个简单的“a=10”的这样一行代码,我们就可以通过上述的这种asttree去分析和修改代码结构。

二.语法树的遍历分析 可以通过ast模块的提供的visitor来对语法树进行遍历。

ast.NodeVisitor是一个专门用来遍历语法树的工具,我们可以通过继承这个类来完成对语法树的遍历以及遍历过程中的处理。

1.visitor的定义 classCodeVisitor(ast.NodeVisitor): defgeneric_visit(self,node): printtype(node).__name__ ast.NodeVisitor.generic_visit(self,node) defvisit_FunctionDef(self,node): printtype(node).__name__ ast.NodeVisitor.generic_visit(self,node) defvisit_Assign(self,node): printtype(node).__name__ ast.NodeVisitor.generic_visit(self,node) 如上述代码,定义类CodeVisitor,继承自NodeVisitor,这里面主要有两种类型的函数,一种的generic_visit,一种是"visit_"+"Node类型"。

visitor首先从根节点root进行遍历,在遍历的过程中,假设节点类型为Assign,如果存在visit_Assign类型的函数,则调用visit_Assgin函数,如果不存在则调用generic_visit函数。

总的来说就是每个节点类型都有专用的类型处理函数,如果不存在,则调用通用的的处理函数generic_visit.关于visitor进行语法树的遍历,stackoverflow上有一篇文章讲的比较详细:Simpleexampleofhowtouseast.NodeVisitor注意:在每个函数处理中,根据需求需要加上ast.NodeVisitor.generic_visit(self,node)这段代码,否则visitor不会继续访问当前节点的子节点。

e.g.如果定义如下的函数:defvisit_Moudle(self,node):   printtype(node).__name__那么,首先访问根节点root,root为Moudle类型,会调用visit_Moudle函数,由于visit_Moudle函数中没有调用NodeVisitor.generic_visit(self,node),所以此次遍历只遍历了根节点root,并没有遍历其他节点。

2.walk方式遍历 也可以通过ast.walk对asttree进行遍历,如下: fornodeinast.walk(tree): ifisinstance(node,ast.FunctionDef): print(node.name) 三.节点的修改 ast模块同样提供了一个NodeTransfomer节点来支持对node的修改,NodeTransfomer继承自NodeVisitor,并重写了generic_visit函数。

对于NodeTransfomer的generic_visit以及visit_+节点类型的函数,都需要返回一个node,可以返回原始node,一个新的替代的node,或者是返回Node代表remove掉这个节点。

假设我们有如下的代码: """asttestcode""" a=10 b="test" printa 我们定义一个NodeTransform的visitor如下: classReWriteName(ast.NodeTransformer): defgeneric_visit(self,node): has_lineno=getattr(node,"lineno","None") col_offset=getattr(node,"col_offset","None") printtype(node).__name__,has_lineno,col_offset ast.NodeTransformer.generic_visit(self,node) returnnode defvisit_Name(self,node): new_node=node ifnode.id=="a": new_node=ast.Name(id="a_rep",ctx=node.ctx) returnnew_node defvisit_Num(self,node): ifnode.n==10: node.n=100 returnnode 在visit_Name中,将变量"a"替换成了变量"a_rep",执行到a=10以及printa的时候,都会将a替换成a_rep,并返回一个新节点。

在visit_Num中,简单粗暴的将10替换成了100,返回修改后的原节点。

我们通过如下方式运用这个NodeTransfomervisitor: file=open("code.py","r") source=file.read() visitor=ReWriteName() root=ast.parse(source) root=visitor.visit(root) ast.fix_missing_locations(root) code_object=compile(root,"","exec") execcode_object ast作用在python解析语法之后,编译成pyCodeObject字节码结构之前,通过NodeTransformer修改后,返回修改后的语法树,我们通过内置模块compile编译成pyCodeObject对象,交给python虚拟机执行。

执行结果:100可以看到,我们同时将a=10和printa两处将a名字换成了a_rep,并将10替换成了100,最后打印的结果是100,成功修改了语法树的节点。

关于节点的修改,这里有比较好的例子可以参考:https://greentreesnakes.readthedocs.org/en/latest/examples.html注意:修改语法树节点,尤其是删除一个语法树节点时要慎重,因为修改或者删除后有可能返回错误的语法树,直到compile或者执行的时候才会发现问题。

通过节点修改pythoncode就可以通过上述方法进行,不过请注意,在运用visitor的代码中有ast.fix_missing_locations(root)这样一行代码,这是因为我们自己创建的节点是不包含lineno以及col_offset这些必要的属性,必须手动修改添加指定,新添加的节点代码的行位置以及偏移位置。

四.修复节点位置 1 属性分析 每个节点都有一些相应的属性,lineno以及col_offset是每个节点都必须有的属性,分别代表行号以及在这行中的偏移。

另外每个节点都有一些自己的特殊属性,如上诉的Module含有body属性,Assign含有targets属性等。

lineno以及col_offset这两个属性,如果是python中原本代码的节点,如Assign、Name、Num等(注:Moudle和Store这样的节点是没有lineno以及col_offset属性的),但是如果我们通过NodeTransFormer新增的节点,默认是不存在这些属性的,我们可以通过三种方法来fix这些节点的lineno以及col_offset属性。

2 属性的修复 我们可以通过相应的方法,对默认没有lineno以及col_offset的节点进行位置的修复,以方便在代码中获取每个节点的位置信息,主要有三种方法进行修复。

1)ast.fix_missing_locations(node)函数递归的将父节点的位置信息(lineno以及col_offset)赋值给没有位置信息的子节点。

2)ast.copy_location(new_node,node)将node的位置信息拷贝给new_node节点,并返回new_node节点。

当我们将旧节点替换成一个新节点的时候,这种方法比较适用。

3)ast.increment_lineno(node,n=1)将node节点以及其所以子节点的行号加上n。

3 分析 我们通过“三.节点的修改"中的例子来分析location信息。

在例子中,我们只有在visit_Name的时候返回的新的节点,这时候节点是没有lineno以及col_offset属性,我们可以通过两种方式获取。

一是如上述代码中,利用ast.fix_missing_locations函数来修复,在"a=10"以及"printa"中,Name节点a跟父节点的lineno相同,但是此时col_offset会有差异。

二是我们将visit_Name的代码修改如下: defvisit_Name(self,node): new_node=node ifnode.id=="a": new_node=ast.Name(id="a_rep",ctx=node.ctx) ast.copy_location(new_node,node) returnnew_node 通过copy_location将旧节点的location信息拷贝给新节点。

参考:GreenTreeSnakes-themissingPythonASTdocs --非常详尽的ast的模块的分析文档。

Simpleexampleofhowtouseast.NodeVisitor--stackoverflow上一篇比较明了的回答InstrumentingtheAST--简单的分析与应用ast—AbstractSyntaxTrees--官方文档AST模块:用Python修改Python代码--比较详细的介绍了修改     怀瑜 关注 关注 25 点赞 踩 4 评论 40 收藏 打赏 扫一扫,分享内容 点击复制链接 专栏目录 浅析AST抽象语法树及Python代码实现 09-21 AbstractSyntaxTree抽象语法树简写为ATS,是相当于用树结构将代码程式表现出来的一种数据结构,这里我们就来浅析AST抽象语法树及Python代码实现 关于python抽象语法树(AST) 最新发布 weixin_42432844的博客 02-16 152 在学习tvmscript的过程中接触到了python抽象语法树,记录一下 lineno col_offset ast.expr和ast.stmt子类的实例有lineno和col_offset属性。

lineno是源代码的行数(从1开始,所以第一行行数是1),而col_offset是该生成节点第一个token的UTF-8字节偏移量。

记录下UTF-8偏移量的原因是parser内部使用UTF-8。

“”“ 什么是上下文管理器? 这里先了解下上下文,上下文是context直译的叫法,在程 评论 4 您还未登录,请先 登录 后发表或查看评论 Python的ast模块 qq_42352516的博客 07-09 268 ast模块 ast模块中的literal_eval方法可以把数据还原成它本身或者是能够转化成的数据类型。

同时在转换时会判断需要计算的内容计算后是不是合法的python类型,如果是则进行运算,否则就不进行运算,比较安全 ... PythonAST的解析和遍历,父子节点的获取,转为字符串等操作 theBlogof等不到天亮丶等时光 04-09 945 如题。

这方面的资料不是很多。

涉及到一点点程序分析,所以在此记录一下。

备注:由于时间关系,我先不贴代码了,我就把我认为比较重要的文献记录下来,有时间再贴代码。

AST模块:用Python修改Python代码 感悟编程 04-02 5685 本文介绍如何利用Python的AST模块得到或者修改python虚拟机编译过程中生成的语法树 CPython的编译过程 在开始之前,我们应该先看看CPython的编译过程,这个过程在 PEP339中有详细的描述。

当然,在读这篇文章的时候,你并不需要对这个步骤有很深入的理解,不过这可以帮助你对整个过程有一个大体的了解。

首先,编译器会根据源代码生成一棵语法分析树(P PythonAst介绍及应用 weixin_34174422的博客 12-15 2231 AbstractSyntaxTrees即抽象语法树。

Ast是python源码到字节码的一种中间产物,借助ast模块可以从语法树的角度分析源码结构。

此外,我们不仅可以修改和执行语法树,还可以将Source生成的语法树unparse成python源码。

因此ast给python源码检查、语法分析、修改代码以及代码调试等留下了足够的发挥空间。

1.AST简介 Python官方提供的CPytho... [364]pythonast模块 周小董 08-06 1万+ 我们知道python解析执行的过程大概是这样的: 词法分析–>具体语法树–>抽象语法树–>控制流图–>字节码–>执行 其中,抽象语法树可以用ast模块建立出来. 首先第一个问题是,这个ast模块有什么用呢?ast提供了访问和修改上述中抽象语法树的功能.可以做一些比如测试,代码生成,静态分析等等.比如pylint,pythons... pythonast_PythonAST处理 weixin_36116139的博客 01-14 369 一般方法是子类ast.NodeVisitor:>>>classVisitCalls(ast.NodeVisitor):...defvisit_Call(self,what):...ifwhat.func.value.id=='self':...printwhat.func.attr...>>>f='''defx(... Pythonast学习笔记1–手动建ast 南山 03-15 4840 Pythonast学习笔记1–手动建ast手动建astpython中的ast模块是非常强大的模块,可以用来修改python源码,或者分析python源码。

为了学习ast模块,先来手动建立一个ast熟悉熟悉。

将用ast来表示下列代码:foo=2 iffoo==2: printfoo else: print"notequal"foo=2foo=2是一个赋值语句,可以分 AST反混淆实战:猿人学爬虫比赛第二题详细题解 Python3爬虫实战1:应对特殊字体,爬取猫眼电影实时排行榜 10-25 1479 缘起应星友要求,写下此文,哎,有钱能使鬼推磨。

实战地址:http://match.yuanrenxue.com/match/2 抓包分析由于谷歌浏览器某些请求不会显示,建议使用火狐浏览器... python抽象语法树_PythonAST–抽象语法树 从零开始的教程世界 07-08 2243 python抽象语法树AbstractSyntaxTreeisaverystrongfeaturesinPython.PythonASTmoduleallowsustointeractwithPythoncodeitselfandmodifyit.抽象语法树是Python中非常强大的功能。

PythonAST模块允许我们与Python代码本身进行交... python中ast模块literal_eval()方法与eval()的区别 lmz_lmz的博客 11-08 4731 Python中,如果要将字符串型的列表,元组,dict转变成原有的类型呢?这个时候你自然会想到eval。

EVAL函数在Python的中做数据类型的转换还是很有用的。

它的作用就是把数据还原成它本身或者是能够转化成的数据类型。

string<==>列表 string<==>元组 string<==>dict 也就是说,使用的eval可以实现从元祖,列... python读取MySQL数据表时,使用ast模块转换decimal格式数据的坑 HHKJ的博客 04-25 539 目录概述解决方案evel()与ast.literal_evel()的区别 概述 MySQL中常用的数据格式有tinyint()、int()、float()、double()、decimal()、varchar、enum()、datetime;小数格式中decimal比较常用,因为更加精确,这里就以decimal为例。

从MySQL中读取了一行数据,内容为:(17479,datetime.dat... python中文文本分析_Python:使用Astmodu分析文本文件中的字符串时出错 weixin_39567222的博客 11-24 19 我有一个文本文件(.txt),其中包含以下两个字符串(这是一个较大文件的片段,其中所有字符串的格式都相同):["('a','1')","('b','2')"]["('c','3')","('d','4')"]我使用下面的代码来解析文本文件中的字符串,以便可以访问每个元素进行数据分析。

如果我将字符串声明为变量,则该代码适用于该字符串,例如:字符串=[“('c','3')”,“('d','... pythonast_PythonCST和AST类似之处的详细介介绍 weixin_31942999的博客 02-02 212 你在计算机相关操作中是否遇到过语法分析所获得的中间结果例如CST,你想知道CST的实际相关应用吗?下面的文章是针对PythonCST的实际相关应用与相关代码的详细介绍,忘你会从中得到自己想要的东西。

PythonCST和AST类似,都是语法分析所获得的中间结果。

他们的不同之处在于,CST直接对应语法分析的匹配的过程,是直接生成的,含有大量冗余信息。

而AST省略了中间的冗余信息,直接对应实... python将c语言程序转变为抽象语法树(ast) weixin_43716339的博客 01-10 507 python使用pycparser库将c语言程序转变为抽象语法树(ast) pycparser库github地址: https://github.com/eliben/pycparser 封装方法 from__future__importprint_function frompycparser.c_astimport* fromutil.remove_zsimportrm_emptyline,rm_includeline,rmCommentsInCFile sys.path.ex AST基础|未学先爽:obfuscator混淆一键还原 Python3爬虫实战1:应对特殊字体,爬取猫眼电影实时排行榜 09-01 645 让新手朋友体验一把通过AST还原混淆代码的快感。

一:先在电脑上安装Cmder,软件下载地址https://cmder.net/ 二:Cmder软件配置地址:https://ww... pythonast_pythonAST抽象语法树 weixin_39888080的博客 02-02 140 AbstractSytaxTree暂时用到的原因:在模型量化中,需要量化某些操作符带来的运算效果,比如'+','-','*','/'等等,这些就需要对源代码进行查询,因此就要需要将python解释器已经将源代码转化为运行的类后,再翻转回源代码参考:https://docs.python.org/3/library/ast.html#ast.NodeTransformerhttps://... pythonAST模块 wangqing008的专栏 02-26 433 todo 详解AST抽象语法树 热门推荐 huangpb的博客 12-04 4万+ 浅谈AST 先来看一下把一个简单的函数转换成AST之后的样子。

//简单函数 functionsquare(n){ returnn*n; } //转换后的AST { type:"FunctionDeclaration", id:{ type:"Identifier", name:"square" }, pa... “相关推荐”对你有帮助么? 非常没帮助 没帮助 一般 有帮助 非常有帮助 提交 ©️2022CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页 怀瑜 CSDN认证博客专家 CSDN认证企业博客 码龄10年 暂无认证 6 原创 49万+ 周排名 162万+ 总排名 3万+ 访问 等级 314 积分 10 粉丝 34 获赞 5 评论 49 收藏 私信 关注 热门文章 pythonast语法分析 32397 计算机的工作原理(基于机器指令的分析) 2334 进程的创建与可执行程序的加载 2098 linux操作系统是如何工作的 1322 深入分析pythonyield 1161 分类专栏 python 1篇 最新评论 pythonast语法分析 风车转呀转: 从https://docs.python.org/3/library/ast.html可以找到PyCF_ONLY_AST的用途 PyCF_ONLY_AST:Generatesandreturnsanabstractsyntaxtreeinsteadofreturningacompiledcodeobject. pythonast语法分析 IMUHERO: 楼主写的很详细,用心了 pythonast语法分析 sanra123: 非常有用,谢谢楼主! pythonast语法分析 杜咩咩不吃草: 请问我解析一个python文件后,如何在现有的代码下添加一个新的函数,主要是如何把这个函数添加到指定位置,用替换节点不行吧,能不能添加节点? 进程的创建与可执行程序的加载 aice_dachong: 博主写的很棒,哈哈 您愿意向朋友推荐“博客详情页”吗? 强烈不推荐 不推荐 一般般 推荐 强烈推荐 提交 最新文章 reactor模式 深入分析pythonyield linux操作系统是如何工作的 2018年1篇 2017年2篇 2013年3篇 目录 目录 分类专栏 python 1篇 目录 打赏作者 怀瑜 你的鼓励将是我创作的最大动力 ¥2 ¥4 ¥6 ¥10 ¥20 输入1-500的整数 余额支付 (余额:--) 扫码支付 扫码支付:¥2 获取中 扫码支付 您的余额不足,请更换扫码支付或充值 打赏作者 实付元 使用余额支付 点击重新获取 扫码支付 钱包余额 0 抵扣说明: 1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。

2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值



請為這篇文章評分?