如何使用python脚本解析python循环?

时间:2013-06-11 08:49:24

标签: python parsing loops instrumentation

我的主要目标是解析python循环,这样我就可以为我的分析插入一些语句。

Normal code:
#A.py

[code Starts]
.
.
.
while [condition]:
    [statements]
    [statements]
    [statements]

.
.
.
[code ends]

检测代码:

Normal code:
#A.py

[code Starts]
.
.
.
count =0                                    <---------- inserted code 
print "Entry of loop"                       <---------- inserted code
while [condition]:
    print "Iteration Number " + count++     <---------- inserted code
    [statements]
    [statements]
    [statements]
print "Exit of loop"                        <---------- inserted code
.
.
.
[code ends]

我的目标是通过适当的缩进将上述代码插入适当的位置。循环也可以是for循环。要实现上述检测代码,我需要解析A.py文件中的循环并插入这些代码。

有没有一种很好的方法来解析这些循环并得到循环的行号,以便我可以进行检测?

谢谢

3 个答案:

答案 0 :(得分:1)

解析通常是一项艰巨的任务。 您可以使用Pygments python库,它是一个语法高亮库。 这似乎与您打算做的不同,但事实并非如此。毕竟,着色代码基本上是将颜色信息添加到代码块中。

使用PythonLexer,您可以为每一行提取标记并添加您想要的任何注释。如果您不想只处理while循环,而且还需要for循环,if语句......

,这将会派上用场

答案 1 :(得分:1)

pyparsing有一个包含完整(?)Python语法分析器的示例文件。从长远来看,这可能是一个有趣的选择 - 尤其是当您的分析项目获得更多功能时

答案 2 :(得分:0)

执行此操作的最简单方法是逐行扫描文件,并在找到匹配的行时添加语句。

以下代码可以满足您的需求,但 非常强大:

def add_info_on_loops(iterable):
    in_loop = False
    for line in iterable:
        if not in_loop:
            if line.startswith('for ') or line.startswith('while '):
                in_loop = True
                yield 'count = 0\n'
                yield 'print "Entry of loop"\n'
                yield line
                yield '    print "Iteration Number:", count'
                yield '    count += 1\n'
            else:
                yield line
        else:
            if not line.startswith('    '):
                in_loop = False
                yield 'print "Exit of loop"\n'
            yield line

用法:

>>> code = StringIO("""[code Starts]
... .
... .
... .
... while [condition]:
...     [statements]
...     [statements]
...     [statements]
... 
... .
... .
... .
... [code ends]""")
>>> print ''.join(add_info_on_loops(code))
[code Starts]
.
.
.
count = 0
print "Entry of loop"
while [condition]:
    print "Iteration Number:", count    count += 1
    [statements]
    [statements]
    [statements]
print "Exit of loop"

.
.
.
[code ends]

代码的缺陷:

  1. 代码在顶层处理循环。像if condition: for x in a: ...这样的东西无法识别。这可以解决在检查我们是否有循环之前剥离空白行(但是你必须考虑不同级别的缩进等)。
  2. 只要循环有一条没有缩进的行,代码就会中断。例如,如果您使用空行“拆分”代码并且IDE剥离空白,则会发生这种情况。解决方案可能是等待非空白的非缩进行而不是非缩进行。
  3. 代码不处理缩进标签(容易修复)
  4. 代码不处理单行循环(例如for x in a: print x)。在这种情况下,您将获得错误的输出。轻松修复:
  5. 之后是否有内容
  6. 如果要添加对嵌套循环的支持,使用单个count变量很麻烦。你应该在某个地方有一个整数id,并使用count_0count_1之类的变量名,每次找到一个新循环时都会增加id。
  7. 代码不处理带有括号的表达式,该表达式没有来自键盘的空格。例如for(a,b) in x:未被检测为循环,而for (a,b) in x:被检测到。这很容易解决。首先,检查行是否以forwhile开头,下一个字符不能是字母,数字,下划线(实际上在python3中,您也可以使用unicode字符,这会变得更难测试,但可能)。
  8. 代码不处理以缩进循环行结尾的源代码。例如for x in a: indented_last_line_of_code()退出print不会被添加。(很容易修复在函数的in_loop之外添加for的检查,看看我们是否有这种情况。)
  9. 正如你所看到的那样,编写一段代码可以完成你所要求的并不是那么简单。 我相信你能做的最好的事情就是使用ast解析代码,然后访问树并在正确的位置添加节点,然后重新访问代码并生成python源代码(通常节点上有指示源代码中的行,允许您复制粘贴完全相同的代码。)