注释Python函数调用带有源代码的字符串

时间:2015-09-14 22:31:43

标签: python regex

我试图从Python源代码中评论函数调用。

我在字符串中读取源代码,然后我尝试应用一些正则表达式来注释方法调用。

这是一个简单的例子:

s = open(path, 'r').read()
# comment method calls
result = re.sub('(^[.\w]+\(.*\))', r'#\1', s, flags=re.MULTILINE)

正如您所看到的,我在源的第一个缩进级别(__name__ == '__main__',方法和类之外的代码)中注释函数

但是,如何让这个正则表达式使用多行调用?

示例,如果我将以下代码转换为字符串:

Builder.load_string('''
    type: 'example'
    callback: my_callback()
''')

如何评论此次通话的每一行?

1 个答案:

答案 0 :(得分:2)

这将为您提供评论所需的行号:

mod = "test1"
mod = importlib.import_module(mod)
p = ast.parse(inspect.getsource(mod))


for n in p.body:
    if isinstance(n, ast.Expr):
        for node in ast.walk(n):
            if isinstance(node, ast.Call):
                print(node.lineno)

对于像

这样的文件
import math

class Foo:
    def __init__(self):
        self.foo = 4
    def bar(self):
        print("hello world")

    def foo(self):
        return self.bar()

def bar():
    return 123

f = Foo()    
f.bar()    
bar()

它将输出1618这两个电话。

这只是忽略这些线条并编写新来源或用更新内容做任何你想做的事情:

import inspect
import importlib
import ast

def get_call_lines(mod):
    mod = importlib.import_module(mod)
    p = ast.parse(inspect.getsource(mod))
    for n in p.body:
        if isinstance(n, ast.Expr):
            for node in ast.walk(n):
                if isinstance(node, ast.Call):
                    yield(node.lineno)


from StringIO import StringIO
new = StringIO()
with open("test1.py") as f:
    st = set(get_call_lines("test1"))
    for ind, line in enumerate(f, 1):
        if ind not in st:
            new.write(line)

new.seek(0)
print(new.read())

new将包含:

import math
class Foo:
    def __init__(self):
        self.foo = 4
    def bar(self):
        print("hello world")

    def foo(self):
        return self.bar()

def bar():
    return 123

f = Foo()

您可以使用ast.NodeTransformer在运行时更改代码,但删除节点并不是一项微不足道的任务,您想要的最简单的方法是忽略正文中的调用行