【问题标题】:How can I parse ast.Assign objects?如何解析 ast.Assign 对象?
【发布时间】:2022-01-22 19:40:19
【问题描述】:

我正在尝试使用 ast 提取有关我的 python 代码的顶级分配的信息,但不太熟悉如何有效地解析它。

例如

import some_module

a = 1
b = some_module.load_number("some_path")

def plus(a,b):
   return a + b

c = plus(a,b)

我希望能够从中提取具有如下数据的赋值表达式列表:

{
'targets' : 'a',
'type' : 'static_value',
'value' : 1
},

{
'targets' : 'b',
'type' : 'function',
'value' : 'some_module.load_number'
'inputs' : ['some_path']
},

{
'targets' : 'c',
'type' : 'function',
'value' : 'plus'
'inputs' : ['var.a', 'var.b']
},

我只关心作业。我目前的方法是这样的。

import ast
with open("test_code.py", "rb") as f:
   content = f.read()
code = ast.parse(content)
results = []

def parse_assignment(node):
   targets = [x.id for x in node.targets] #extract variables names being assigned to

   ### Extract assigned values for primitives; only str shown for brevity
   if isinstance(node.value, ast.Str):
      values = [node.value.s]
      type = 'str'
   
   ### Function call version
   elif isinstance(node.value, ast.Call):
      values = [node.value.func.value.id],
      type = ['function']

   return {'targets' : targets, 'values' : values, 'types' : types}

for node in ast.walk(code):
   if isinstance(node, ast.Assign):
      print(node)
      results = results + parse_assignment(node)

这里显示的方法有两个问题:

  1. 我不认为ast.walk 在这里是一个好主意,因为它似乎是递归的,并且可能会在函数定义或其他内容中获取分配。我只想要顶级作业。

  2. 我解析函数名称的方式似乎不正确。在这个例子中,我想解析出some_module.load_number,但我得到的是some_module。如何从 ast.Call 对象中获取完整的函数名称?

【问题讨论】:

    标签: python python-3.x abstract-syntax-tree


    【解决方案1】:

    不用ast.walk,只需遍历code.body 并挑选出Assign 对象。

    关于函数名,Call值有一个func属性,其值为Attribute节点,其value为模块名,attr为实际引用函数的属性.

    >>> >>> call = code.body[2].value.func
    >>> f'{call.value.id}.{call.attr}'
    'some_module.load_number'
    

    请注意,一般情况下,Call 节点的func 属性可以是任意表达式,其运行时值是可调用的。

    【讨论】:

      猜你喜欢
      • 2018-05-30
      • 2021-08-14
      • 2012-09-28
      • 2017-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多