如何解析python代码以识别全局变量的使用



我使用python来解析python代码。假设我正在解析的代码是:

def foo():
    global x, y
    x = 1
    y = 2
    print x + y

我想在代码中找到全局变量x和y的所有使用。我有一个提前使用的全局变量列表,所以不需要从全局变量行中提取x和y。所以问题是:给定一些python代码中使用的已知全局变量列表,例如在这种情况下['x', 'y'],我如何解析代码以找到这些全局变量的用途?

您可以使用ast来解析python代码

from __future__ import print_function
import ast
src = """def foo():
    global x, y 
    x = y = 1
    y = 2
    print x + y"""

s = ast.parse(src)
gvars = set()
for i in ast.walk(s):
    # get globals
    if isinstance(i,ast.Global):
        for j in ast.walk(i):
            gvars = gvars.union(i.names)
    #get id-s of globals
    for (field_type,value) in ast.iter_fields(i):
        if field_type == "id" and value in gvars:
            print(value , "at line", i.lineno)
这个输出

x at line 3
y at line 3
y at line 4
x at line 5
y at line 5

这仍然不能正确地在作用域上工作,但仍然可以找到source中某个id的所有实例。

范围解析问题的示例:

global x,y
def foo():
    x = y = 1 
    global y
    x = y = 2
    # only global y is 2
def bar():
    #here x and y are not global
    x = y = 3
foo()
bar()
print(x,y) # runtime error. x undefined 

我们希望代码只生成
-函数
- x,y在end
但是它会打印所有x y

这将花费您相当多的时间,因为查找变量不是简单的解析或正则表达式工作。让我们考虑一下这个例子:

def foo():
    global x, y
    x = 1  # x is one
    y = 2
    print x + y
    def x(y):
        x print y
    class x:
        y = 'lol'

这里我们给出了xy有效和无效的一些情况。您可以尽量保持简单,编写一个脚本,跟踪正在解析的行(无论是函数定义还是类变量)的上下文,并包含您能想到的所有使用全局变量的情况。

正式的方法是使用词法和语法分析器。词法分析器解析代码并将词素(单词)发送给语法分析器,语法分析器基本上是一个程序,用于确定词素流是否(以及如何)符合某种语言的形式语法。非正式地说,形式语法是一组规则,它决定了语言应该是什么样子:

<global_definition> ::= 'global' <variables_list>
<varirable_assignment> ::= <variable> '=' <expression>
# and so on

这是大量的工作,但幸运的是它是在Python标准库中完成的。正如@LukaRahne提到的,最后一个模块将是一个好的开始。另一方面,如果您对ast后端(以及一般如何使用源代码来控制计算机)感兴趣,我建议您看看compiler theory教科书或文章。

我为我在这里犯的英语错误道歉。我还没有掌握它的形式语法

这将满足您的要求:

vars = ['x', 'y']
with open('filename') as fin:  
    for ln in fin:
        vals = ln.split()
        for var in vars:
            if var in vals:
                print ln