python ast模块使用

Python 的抽象语法树库ast 最后,我们使用 ast 的 unparse() 方法将修改后的抽象语法树转换为 Python 代码,并输出新代码。在这个例子中,我们首先定义了一个 Python 代码块,并将其传递给 ast 的 parse() 方法,将其解析为抽象语法树。Python 的 ast(Abstract Syntax Trees,抽象语法树)库是 Python 标准库中提供的一个模块,它可以帮助你在 Python 中解析和分析代码的抽象语法树。然后我们使用 ast 的 walk() 方法遍历抽象语法树,并提取所有的变量名。 阅读详情
AI摘要

本文详细介绍了Python的AST(抽象语法树)模块,包括如何获取和遍历AST,以及如何通过NodeTransformer修改代码。AST在Python代码解析后、编译成字节码前发挥作用,可用于代码分析和重构。通过示例展示了如何使用ast.parse创建语法树,使用NodeVisitor遍历和修改节点,以及修复缺失的位置信息。

ast(Abstract Syntax Trees)是python中非常有用的一个模块,我们可以通过分析python的抽象语法树来对python的代码进行分析和修改。
ast作用在python代码的语法被解析后,被编译成字节码之前。

一. ast

1. 获取语法树

ast模块的基本使用是非常简单的,我们可以通过如下代码快速得到一棵抽象语法树:

import ast
root_node = ast.parse("print 'hello world'")
root_node -> <_ast.Module object at 0x9e3df6c>

通过ast的parse方法得到ast tree的根节点root_node, 我看可以通过根节点来遍历语法树,从而对python代码进行分析和修改。
ast.parse(可以直接查看ast模块的源代码)方法实际上是调用内置函数compile进行编译,如下所示:

def parse(source, filename='<unknown>', mode='exec'):
    """
    Parse the source into an AST node.
    Equivalent to compile(source, filename, mode, PyCF_ONLY_AST).
    """
    return compile(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”的这样一行代码,我们就可以通过上述的这种ast tree去分析和修改代码结构。

二. 语法树的遍历分析

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

1. visitor的定义

class CodeVisitor(ast.NodeVisitor):
    def generic_visit(self, node):
        print type(node).__name__
        ast.NodeVisitor.generic_visit(self, node)
 
    def visit_FunctionDef(self, node):
        print type(node).__name__
        ast.NodeVisitor.generic_visit(self, node)
 
    def visit_Assign(self, node):
        print type(node).__name__

如上述代码,定义类CodeVisitor,继承自NodeVisitor,这里面主要有两种类型的函数,一种的generic_visit,一种是"visit_" + "Node类型"。
visitor首先从根节点root进行遍历,在遍历的过程中,假设节点类型为Assign,如果存在visit_Assign类型的函数,则调用visit_Assgin函数,如果不存在则调用generic_visit函数。
总的来说就是每个节点类型都有专用的类型处理函数,如果不存在,则调用通用的的处理函数generic_visit.
关于visitor进行语法树的遍历,stackoverflow上有一篇文章讲的比较详细:Simple example of how to use ast.NodeVisitor
注意:
在每个函数处理中,根据需求需要加上ast.NodeVisitor.generic_visit(self, node)这段代码,否则visitor不会继续访问当前节点的子节点。
e.g. 如果定义如下的函数:
def visit_Moudle(self, node):
     print type(node).__name__
那么,首先访问根节点root,root为Moudle类型,会调用visit_Moudle函数,由于visit_Moudle函数中没有调用NodeVisitor.generic_visit(self, node),所以此次遍历只遍历了根节点root,并没有遍历其他节点。

2. walk方式遍历

也可以通过ast.walk对ast tree进行遍历,如下:

for node in ast.walk(tree):
    if isinstance(node, ast.FunctionDef):
        print(node.name)

三. 节点的修改

ast模块同样提供了一个NodeTransfomer节点来支持对node的修改,NodeTransfomer继承自NodeVisitor,并重写了generic_visit函数。
对于NodeTransfomer的generic_visit以及visit_ + 节点类型的函数,都需要返回一个node,可以返回原始node,一个新的替代的node,或者是返回Node代表remove掉这个节点。
假设我们有如下的代码:

"""ast test code"""
a = 10
b = "test"
print a

我们定义一个NodeTransform的visitor如下:

class ReWriteName(ast.NodeTransformer):
    def generic_visit(self, node):
        has_lineno = getattr(node, "lineno", "None")
        col_offset = getattr(node, "col_offset", "None")
        print type(node).__name__, has_lineno, col_offset
        ast.NodeTransformer.generic_visit(self, node)
        return node
 
    def visit_Name(self, node):
        new_node = node
        if node.id == "a":
            new_node = ast.Name(id = "a_rep", ctx = node.ctx)
        return new_node
 
    def visit_Num(self, node):
        if node.n == 10:
            node.n = 100
        return node

在visit_Name中,将变量"a"替换成了变量"a_rep",执行到a = 10以及print a的时候,都会将a替换成a_rep,并返回一个新节点。
在visit_Num中,简单粗暴的将10替换成了100,返回修改后的原节点。
我们通过如下方式运用这个NodeTransfomer visitor:

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, "<string>", "exec")
exec code_object

ast作用在python解析语法之后,编译成pyCodeObject字节码结构之前,通过NodeTransformer修改后,返回修改后的语法树,我们通过内置模块compile编译成pyCodeObject对象,交给python虚拟机执行。
执行结果:100
可以看到,我们同时将a = 10和print a两处将a名字换成了a_rep,并将10替换成了100,最后打印的结果是100,成功修改了语法树的节点。
关于节点的修改,这里有比较好的例子可以参考:https://greentreesnakes.readthedocs.org/en/latest/examples.html
注意:
修改语法树节点,尤其是删除一个语法树节点时要慎重,因为修改或者删除后有可能返回错误的语法树,直到compile或者执行的时候才会发现问题。
通过节点修改python code就可以通过上述方法进行,不过请注意,在运用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"以及"print a"中,Name节点a跟父节点的lineno相同,但是此时col_offset会有差异。
二是我们将visit_Name的代码修改如下:

def visit_Name(self, node):
    new_node = node
    if node.id == "a":
        new_node = ast.Name(id = "a_rep", ctx = node.ctx)
        ast.copy_location(new_node, node)
    return new_node

通过copy_location将旧节点的location信息拷贝给新节点。

参考:
Green Tree Snakes - the missing Python AST docs --非常详尽的ast的模块的分析文档。
Simple example of how to use ast.NodeVisitor --stackoverflow上一篇比较明了的回答
Instrumenting the AST --简单的分析与应用
ast — Abstract Syntax Trees --官方文档
AST 模块:用 Python 修改 Python 代码 --比较详细的介绍了修改

 

转载于https://blog.youkuaiyun.com/ma89481508/article/details/56017697

python的ast库的使用 用Python的ast库,提取Python代码文件中的所有函数。在Python中,可以使用ast库来解析Python代码,并通过遍历AST树来找到其中的函数定义。抽象语法树是Python源代码的一种树形表示形式,用于表示Python代码的语法结构。Python的ast模块可以将Python代码解析为AST,并提供了许多方法和属性,以便开发者可以访问和修改AST节点。Python的ast模块是一个用于处理Python代码抽象语法树(AST)的库。 阅读详情

相关推荐

代码炼金术:用 Python AST 模块重塑高效条件语句

本文将聚焦于 **使用 `ast` 模块重构复杂的条件语句**。 我们将通过一个具体的示例,演示如何将一个低效的嵌套条件语句,重构为更高效、更简洁的结构,并分析重构前后的代码性能差异。 我们将手把手地带您体验 AST 代码重构的 “炼金术”,让您掌握这一强大的代码优化技巧,提升您的 Python 代码功力!

铭渊老黄 225

python ast 详解与用法

来说,我们可以先解析成抽象语法树,然后打印所有的结点,如下所示。在 python 中,我们可以通过自带的 ast 模块来对解析遍历语法树,通过ast.parse()可以将字符串代码解析为抽象语法树,然后通过ast.dump()可以打印这棵语法树。上面的简单示例向我们展示了几种基本结点类型(Assign、Name、Constant),接下来我们将会展示其他几种常见的结点类型和示例,完整的节点类型可以查阅。对于上面的例子,我们通过可视化可以看到,顶层是一个ast.Expr类型的结点,表示一个表达式。

hjyp的博客 1万+

Python ast模块(Abstract Syntax Trees,抽象语法树)介绍及使用

Python的ast模块提供了抽象语法树(AST)功能,可用于解析、分析和修改Python代码结构。它支持将代码转换为可操作的树形结构,包含Module、FunctionDef等节点类型,通过parse()、walk()、NodeVisitor等工具实现代码分析和转换。特别值得关注的是ast.literal_eval()方法,它能安全地解析字符串形式的Python字面量或容器数据,相比eval()更安全,适用于配置文件解析等场景。该模块广泛应用于代码分析、生成、转换和优化,是构建代码检查器和重构工具的基础。

Cachel Wood的博客 303

Python-AST语法树

在计算机科学中,AST),是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码。AST是在处理源代码时所使用的一种中间表示形式,在编译和代码生成过程中起着关键作用。之所以说语法是「抽象」的,是因为这里的语法并不会表示出真实语法中出现的每个细节。AST中的每个节点表示源代码中的一个语法构造,如变量声明、表达式、函数调用、控制结构等。。例如,一个函数声明的AST节点可能包含多个子节点,如函数名、参数列表和函数体等。

Rnan_prince的博客 9064

ast-parser:AST解析器

AST解析器 $ npm i ast-parser -D const { parse : babelParse } = require ( "@babel/parser" ) ; const { parse : astParse , find , findInfo } = require ( "ast-parser" ) ; function getNode ( code ) { return babelParse ( code , { sourceType : "module" , plugins : [ "classProperties" , "typescript" ] , } ) ; } expect ( astParse ( getNode ( code ) ) . nodeType ) . toBe ( "File" ) ; expect ( astP

Android逆向实战:通过smali/baksmali动态注入DEX逻辑

本文详细介绍了在无源码条件下对Android应用进行动态逻辑注入的实战方法。通过使用smali和baksmali工具对DEX文件进行反编译、修改与重打包,实现在目标方法中插入自定义代码(如日志打印),并分享了定位目标、处理寄存器、避免常见错误的实用技巧与避坑指南。

weixin_29008691的博客 364

Python AST 模块实战解析

Python 的 ast 模块用于处理代码的抽象语法树(AST),可将代码转换为结构化树形表示,便于分析、修改或生成新代码。核心功能包括解析代码生成 AST(ast.parse())、查看结构(ast.dump())、遍历节点(ast.NodeVisitor 和 ast.walk())、修改 AST(ast.NodeTransformer)以及将 AST 编译回可执行代码(compile())。此外,ast.literal_eval() 提供安全的表达式求值。该模块在代码分析、自动化重构和静态检查等场景中非

学习代码 1302

增量编码器资讯大全

增量编码器是什么 增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小,按照工作原理编码器可分为增量式和绝对式两类。 增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。 编码器是把角位移或直线位移转换成电信号的一种装置。前者称为码盘,后者称码尺.按照读出方式编码器可以分为接触式和非接触式两种.接触式采...

kindele的博客 6008

【python】ast模块介绍和使用

ast模块的使用,包括ast.NodeVisitor和ast.NodeTransformer等的使用

guozhibin123的博客 3036

PyTorch深度学习实战(3)——使用PyTorch构建神经网络

PyTorch 是一个用于构建深度神经网络的库,具有灵活性和可扩展性,可以轻松自定义模型。在本节中,我们将使用 PyTorch 库构建神经网络,利用张量对象操作和梯度值计算更新网络权重,并利用 Sequential 类简化网络构建过程,最后还介绍了如何使用 save、load 方法保存和加载模型,以节省模型训练时间。

盼小辉丶的博客 8万+

ADBC 全面解析:ABAP 开发者玩转 Native SQL 的实战指南

本文介绍了 SAP ABAP 中的 ADBC(ABAP Database Connectivity)技术,它是一种基于 ABAP 面向对象的类库,用于访问 Native SQL 接口。与 Open SQL 和 EXEC SQL 相比,ADBC 具有以下优势:支持特定数据库语法、可访问二级数据库连接、执行多种 SQL 操作且语法更 ABAP 化。文章通过示例展示了 ADBC 的基本用法,包括创建语句对象、执行查询和处理结果集。建议在需要数据库特有功能或二级连接时优先使用 ADBC,同时提供封装类来简化调用。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 308

python中的ast模块介绍和使用

新建节点时,节点的lineno和col_offset这两个属性需要关注下,我们手动创建的节点默认不带这两个属性,但是ast解析的语法树中的节点携带,且需要这两个属性。从语法树中可以看出,该语句加载(Load())了名(Name())为print的函数接口(func),函数传参(args)是值为’hello world’(value)的常量(Constant)。value是单个节点。4、实例化我们定义的查找的类,然后调用接口visit(node=xxx),xxx为抽象语法树的根节点,从而实现遍历查找动作。

skytttttt9394的博客 4676

基于FPGA的时间数字转换(TDC)设计(一:原理)

基于FPGA的时间数字转换(TDC)设计,此为第一篇

sdau2005的博客 5070

python中ast模块的详解与用法

ast模块(Abstract Syntax Tree)是Python标准库的一部分,它提供了一个抽象语法树的API,用于解析Python代码并将其转换为树状结构。这种树状结构称为抽象语法树,它是一种中间表示形式,用于代码分析、修改和生成。

weixin_54897474的博客 5836

JMeter压力测试全攻略:从入门到精通

本文系统讲解JMeter压力测试的完整流程与结果评估方法。开篇介绍压力测试的核心概念及JMeter工具特性,随后从环境搭建入手,详细说明JDK配置、JMeter安装及中文界面设置。主体部分围绕测试流程展开,涵盖测试计划创建、线程组参数调优、HTTP请求配置、断言与监听器添加等实操步骤;结果评估环节深入解析聚合报告指标、结果树分析及性能瓶颈定位方法,并通过电商接口测试案例演示全流程应用。文末总结关键要点,为读者提供从基础操作到分布式压测、性能调优的进阶学习方向,助力掌握JMeter在系统性能评估中的核心应用。

邓邓子的博客 2416

SAP 管道业务(Pipeline Procurement)是用于水、电、气等不间断供应且无库存管理的物料采购场景,核心是消耗即记账、无库存持有,通过 MM-FI 集成实现实时负债与成本过账

摘要:SAP管道业务适用于水电气等无库存管理的物料采购场景,通过消耗即记账机制实现实时负债与成本过账。核心配置包括创建PIPE物料类型(无库存管理)、维护管道采购信息记录、配置自动记账科目等。SAP PO可集成外部系统实现流程自动化,如自动过账提取数据、发票校验等。实施要点在于物料主数据、信息记录和科目确定的精准配置,以及PO接口的可靠对接,最终构建端到端的高效采购与财务结算体系。

金牌架构师 748

Python ast 模块使用

推广博客: Python ast 模块使用

Elegant Coding 572

ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(一)

本系列文章主要针对ROS机器人常使用的未知环境自主探索功能包explore_lite展开全源码的详细解析,并进行概括总结。 本系列文章共包含六篇文章,前五篇文章主要介绍explore_lite功能包中 explore.cpp、costmap_tools.h、frontier_search.cpp、costmap_client.cpp等源码实现文件中全部函数的详细介绍,第六篇文章进行概括总结,包含自主探索功能包explore_lite的简介,实现未知环境自主探索功能的原理及流程总结,效果演示,使用功能包

慕羽★的博客 3936

[364]python ast模块

我们知道python解析执行的过程大概是这样的: 词法分析 –&gt; 具体语法树 –&gt; 抽象语法树 –&gt; 控制流图 –&gt; 字节码 –&gt; 执行 其中,抽象语法树可以用ast模块建立出来. 首先第一个问题是, 这个ast模块有什么用呢? ast提供了访问和修改上述中抽象语法树的功能.可以做一些比如测试,代码生成,静态分析等等. 比如pylint, pythons...

周小董 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Python的ast模块

ast模块 ast模块中的literal_eval方法可以把数据还原成它本身或者是能够转化成的数据类型。同时在转换时会判断需要计算的内容计算后是不是合法的python类型,如果是则进行运算,否则就不进行运算,比较安全 ...

qq_42352516的博客 5546

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

AST 模块:用 Python 修改 Python 代码

本文介绍如何利用Python的AST模块得到或者修改python虚拟机编译过程中生成的语法树 CPython 的编译过程 在开始之前,我们应该先看看 CPython 的编译过程,这个过程在 PEP 339 中有详细的描述。 当然,在读这篇文章的时候,你并不需要对这个步骤有很深入的理解,不过这可以帮助你对整个过程有一个大体的了解。 首先,编译器会根据源代码生成一棵语法分析树 (P

感悟编程 7221

python AST模块

todo

wangqing008的专栏 748

Python ast和json模块的数据转化

在现在的项目交集越来越多的智能时代,需要调用的第三方接口会越来越多,所以对数据的转化也会越来愈多,下面我给大家讲解Python中的两个模块,他们都具有处理数据的能力。 ast模块 如果需要把一大长串的字符串数据转化为json数据,那么我会第一个想到使用ast模块,因为他比json模块使用更加简单。 代码如下: data_json = ast.literal_eval(data) 哇哈哈...

何以清风 3398

彻底搞懂Python抽象语法树:ast模块实战指南

你还在为理解Python代码解析原理而烦恼?是否想过如何在不执行代码的情况下分析其结构?本文将带你从零掌握抽象语法树(Abstract Syntax Tree, AST)的核心概念,通过CPython官方`ast`模块的实战案例,让你轻松实现代码静态分析、自动化重构和自定义语法检查。读完本文,你将能够: - 理解AST在Python解释器中的关键作用 - 掌握`ast`模块的核心API与节点类型 ...

gitblog_00520的博客 516

Python 库手册:ast 抽象语法树模块

ast(Abstract Syntax Trees,抽象语法树)模块用于将 Python 源代码转换为语法树结构,从而支持对代码进行分析、转换和再生成。该模块广泛应用于编译器、代码检查工具、自动化代码修改、静态分析器(如 mypy、flake8)和安全沙箱环境中。每个 Python 语法元素(如函数定义、if 语句、for 循环)在 AST 中都有对应的类(如 FunctionDef, If, For)。安全地对字符串或表达式求值,仅支持字面量(如列表、字典、数值、字符串)。

qq_41176800的博客 1459

记一次用Python的ast模块将Flask项目转为Quart的尝试

里面的代码因为是在两天内写完的,而且也只用一次,所以有很多不完善的地方,也没有写的非常精细。当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。有了理论,剩下的事就是对照着 pprint 出的 AST,按对应的结构一点点写代码了。

weixin_68789096的博客 1072
上一篇: 快速排序
下一篇: 2020-12-07
ThinkTimes
博客等级 码龄9年 4粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值