Как получить первый аргумент вызова функции через AST?

#python #abstract-syntax-tree

#питон #абстрактно-синтаксическое дерево

Вопрос:

Я пытаюсь получить аргументы из вызова функции. Например, у нас есть такой пример вызова функции:

 self.assertEqual(dictlike.fromkeys('a'), {'a':None})  

Я использую такой код:

 import ast   class CallVisitor(ast.NodeVisitor):  def visit_Call(self, node):  print('Node type: CallnFields: ', node._fields)  ast.NodeVisitor.generic_visit(self, node)   def visit_Name(self, node):  print('Node type: NamenFields: ', node._fields)  ast.NodeVisitor.generic_visit(self, node)   def visit_Constant(self, node):  print('Node type: ConstantnFields: ', node._fields)  ast.NodeVisitor.generic_visit(self, node)   def visit_keyword(self, node):  print('Node type: keywordnFields: ', node._fields)  ast.NodeVisitor.generic_visit(self, node)   def visit_FunctionDef(self,node):  print('Node type: FunctionDefnFields:', node.fields)  ast.NodeVisitor.generic_visit(self, node)   if __name__ == '__main__':  source = """self.assertEqual(dictlike.fromkeys('a'), {'a':None})"""   root = ast.parse(source)  for node in ast.walk(root):  if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Store):  print(node.id)  elif isinstance(node, ast.Attribute):  print(node.attr)  

и я получаю такой результат:

 assertEqual fromkeys  

Я также пытался достать его со свалки: печать (ast.дамп(узел))

но мне не удалось получить определенное поле:

 Module(body=[Expr(value=Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertEqual', ctx=Load()), args=[Call(func=Attribute(value=Name(id='dictlike', ctx=Load()), attr='fromkeys', ctx=Load()), args=[Constant(value='a', kind=None)], keywords=[]), Dict(keys=[Constant(value='a', kind=None)], values=[Constant(value=None, kind=None)])], keywords=[]))], type_ignores=[])  

например, я попробовал такой способ:

 print(node.args[0])  

наконец, я хотел бы получить:

 dictlike.fromkeys('a')  

может быть, я сделал что-то не так ?

Ответ №1:

Предполагая, что вы пытаетесь извлечь параметры из тестовых случаев утверждения в исходном коде, вы можете использовать ast.walk :

 import ast source = """self.assertEqual(dictlike.fromkeys('a'), {'a':None})""" r = [[*map(ast.unparse, i.args i.keywords)] for i in ast.walk(ast.parse(source))   if isinstance(i, ast.Call) and getattr(i.func, 'attr', '').startswith('assert')]  

Выход:

 [["dictlike.fromkeys('a')", "{'a': None}"]]  

Комментарии:

1. спасибо за ваш ответ, но я получил эту ошибку при выполнении вашего кода — AttributeError: module 'ast' has no attribute 'unparse' а также такое предупреждение, которое у меня есть Expected type 'List[expr]' (matched generic type 'List[_T]'), got 'List[keyword]' instead в коде

2. @Andrew ast.unparse доступен только в версиях Python gt;=3.9.