使用源代码以字符串形式注释Python函数调用

使用源代码以字符串形式注释Python函数调用,python,regex,Python,Regex,我试图对Python源代码中的函数调用进行注释 我阅读了字符串中的源代码,然后尝试将一些正则表达式应用于注释方法调用 下面是一个简单的工作示例: s = open(path, 'r').read() # comment method calls result = re.sub('(^[.\w]+\(.*\))', r'#\1', s, flags=re.MULTILINE) 如您所见,我在源代码的第一个缩进级别对函数进行注释(在\uuuuuu name\uuuuuuu=='\uuuuuuuuu

我试图对Python源代码中的函数调用进行注释

我阅读了字符串中的源代码,然后尝试将一些正则表达式应用于注释方法调用

下面是一个简单的工作示例:

s = open(path, 'r').read()
# comment method calls
result = re.sub('(^[.\w]+\(.*\))', r'#\1', s, flags=re.MULTILINE)
如您所见,我在源代码的第一个缩进级别对函数进行注释(在
\uuuuuu name\uuuuuuu=='\uuuuuuuuu main\uuuuuu'
之外的代码、方法和类)

但是,如何使这个正则表达式在多行调用中工作

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

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

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

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

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()
它将输出两个调用的
16
18

只需忽略这些行并编写新的源代码,或对更新内容执行任何操作:

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())
新文件将包括:

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
在运行时更改代码,但删除节点并不是一项简单的任务,最简单的方法是忽略正文中的调用行

我认为这不是regexp的一项支持性工作。也许您应该尝试使用更具体的解析器:查看模块可能会有所帮助为什么要注释每一行?你想实现什么?你只想在运行时实现吗?所以你不关心任何逻辑,即创建实例,你只想导入没有任何运行的类?没问题,欢迎你,就像我在回答中说的,还有其他方法,但它们更复杂,对于您需要的内容,这应该是最直接的方法。