在Python中将节点添加到AST时,函数不会添加到新行中

2024-06-16 10:55:51 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中,我尝试使用AST在源代码中的每个for循环之后添加print语句。但是,问题是print语句并没有添加到新行,而是添加到了for循环的同一行。添加fix_missing_locations()increment_lineno()的各种组合没有帮助。我做错什么了?在

import astor
import ast

class CodeInstrumentator(ast.NodeTransformer):
    def get_print_stmt(self, lineno):
        return ast.Call(
            func=ast.Name(id='print', ctx=ast.Load()),
            args=[ast.Num(n=lineno)],
            keywords=[]
            )

    def insert_print(self, node):
        node.body.insert(0, self.get_print_stmt(node.lineno))

    def visit_For(self, node):
        self.insert_print(node)
        self.generic_visit(node)
        return node

def main():
    input_file = 'source.py'
    try:
        myAST = astor.parsefile(input_file)
    except Exception as e:
        raise e

    CodeInstrumentator().visit(myAST)
    instru_source = astor.to_source(myAST)
    source_file = open('test.py', 'w')
    source_file.write(instru_source)

if __name__ == "__main__":
    main()

Tags: selfnodesourceformaindef语句visit
1条回答
网友
1楼 · 发布于 2024-06-16 10:55:51

这个问题似乎被我抛弃了,我正面临着一个类似的问题,我终于找到了一个解决办法,所以我把它写下来,以防万一它对某些人有用。在

首先,请注意,ASTOR不依赖于lineno或{},因此使用ast.fix_missing_locations(node)increment_lineno(node, n=1)或{}不会对输出代码产生任何影响。在

这就是说,问题是Call语句不是一个独立的操作,因此,ASTOR将它应用于前一个节点(因为它是同一个操作的一部分,但是您没有写入该节点的lineno)。在

然后,解决方案是使用Expr语句用void调用包装Call语句:

def get_print_stmt(self, lineno):
    return ast.Expr(value=ast.Call(
        func=ast.Name(id='print', ctx=ast.Load()),
        args=[ast.Num(n=lineno)],
        keywords=[]
        ))

如果编写的代码包含对函数的void调用,您会注意到它的AST表示已经包含Expr节点:

测试_文件.py

^{pr2}$

过程_文件.py

#!/usr/bin/python

# -*- coding: utf-8 -*-

from __future__ import print_function

def main():
    tree = astor.code_to_ast.parse_file("test_file.py")

    print("DUMP TREE")
    print(astor.dump_tree(tree))
    print("SOURCE")
    print(astor.to_source(tree))

#
# MAIN
#

if __name__ == '__main__':
    main()

输出

$ python process_file.py

DUMP TREE
Module(
    body=[
        Expr(value=Call(func=Name(id='my_func'), args=[], keywords=[], starargs=None, kwargs=None))])
SOURCE
my_func()

相关问题 更多 >