python ast 语法分析_怀瑜的博客
文章推薦指數: 80 %
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='
(关于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,"
执行结果: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币套餐、付费专栏及课程。
余额充值
延伸文章資訊
- 1Python Ast介绍及应用 - 博客园
Ast是python源码到字节码的一种中间产物,借助ast模块可以从语法树的角度分析源码结构。此外,我们不仅可以修改和执行语法树,还可以将Source生成的语法树 ...
- 2Python ast.AST用法及代碼示例- 純淨天空
用法: class ast.AST. 這是所有AST 節點類的基礎。實際的節點類派生自 Parser/Python.asdl 文件,該文件在下麵複製。它們在 _ast C 模塊中定義,並在 as...
- 3AST 模块:用Python 修改Python 代码 - PyCoder's Weekly ...
在这篇文章中,我们将看到如何使用 ast 模块对Python 代码进行修改,同时还将看到一些使用了这个技术的工具。 CPython 的编译过程¶. http://pyimg.fanhe.org/...
- 4ast --- 抽象语法树— Python 3.8.13 說明文件
ast 模块帮助Python 程序处理Python 语法的抽象语法树。抽象语法或许会随着Python 的更新发布而改变;该模块能够帮助理解当前语法在编程层面的样貌。
- 5Python ast 模块使用