模块级常量的Python正则表达式

模块级常量的Python正则表达式,python,regex,full-text-search,Python,Regex,Full Text Search,我回过头来,期待着一个可能的解决方案,但我想我的谷歌fu今天很差。更不用说我对正则表达式的了解了,它几乎为零 我试图仅使用文本处理从一系列Python文件中检索一些“常量”(即模块级全局变量)的定义。基本上,我阅读Python文件的全部文本,然后对文本应用正则表达式来找出这些“常量”的位置/内容 例如,我的Python文件中可以有如下内容: CONSTANT_ONE = 0 # standard CONSTANT_RIGHT = 1 # rotation of 90 on the

我回过头来,期待着一个可能的解决方案,但我想我的谷歌fu今天很差。更不用说我对正则表达式的了解了,它几乎为零

我试图仅使用文本处理从一系列Python文件中检索一些“常量”(即模块级全局变量)的定义。基本上,我阅读Python文件的全部文本,然后对文本应用正则表达式来找出这些“常量”的位置/内容

例如,我的Python文件中可以有如下内容:

CONSTANT_ONE   = 0    # standard
CONSTANT_RIGHT = 1    # rotation of 90 on the right
CONSTANT_LEFT  = 2    # rotation of 90 on the left
我发现这个正则表达式可以提取变量名:

但是,它在以下声明中严重失败:

NAME1, NAME2 = 0, None
CONST_1, CONST_2, CONST_3 = range(3)
有没有办法修改我的正则表达式来处理这两种情况?我很抱歉,如果这是一个非常基本的问题,但我真的不是正则表达式专家

先谢谢你


Andrea.

我认为没有一种简单的方法可以使用正则表达式实现这一点。可以
编译
Python模块并沿着
AST
查找变量定义。请参阅和上的文档

编辑:我当前的程序,使用@Sven的想法

#!/usr/bin/env python

import ast
import sys

# example assignment.
a, b=5, 9

class MyNodeVisitor(ast.NodeVisitor):
        """
        Visit nodes in AST. Idea from @Sven.
        """
        def visit_Name(self, node):
                if isinstance(node.ctx, ast.Store):
                        print "Assigning name '%s' on line %d" % ( \
                                node.id, node.lineno)
        def visit_FunctionDef(self, node):
                pass
        def visit_ClassDef(self, node):
                pass

def printAssignments(name):
        """
        Read Python file and print a list of variable assignments.
        """
        # read file.
        f=open(name, 'rU')
        data=f.readlines()
        f.close()

        # create AST.
        t=ast.parse("".join(data), filename=name, mode='exec')

        # find assignments.
        MyNodeVisitor().visit(t)

        # walk nodes.
        # for node in ast.walk(t):
        #       if isinstance(node, ast.Name) \
        #          and isinstance(node.ctx, ast.Store) \
        #          and node.col_offset == 0:
        #               print "Assigning name '%s' on line %d" % (node.id, node.lineno)

# print all assignments from files.
for name in sys.argv[1:]:
        print "=== %s ===" % name
        printAssignments(name)
        print "====%s====" % ('='*len(name), )

不要使用正则表达式,而是使用Python的解析器。这要简单得多:

class TargetExtractor(ast.NodeVisitor):
    def visit_Name(self, node):
        if isinstance(node.ctx, ast.Store):
            print node.id
    def visit_FunctionDef(self, node):
        pass
    def visit_ClassDef(self, node):
        pass

TargetExtractor().visit(ast.parse("a, b = 2, 3; c = d"))
印刷品

a
b
c

您还可以将文件的全部内容传递给
ast.parse()

而不是字符串,我不知道您这样做的目的是什么,但是如果出于某些原因它必须是正则表达式(如果不是Svens,那么答案似乎很好+1),这里将是一个:

^([\w\s,]+)=
看到这里了吗


但是这比你想要的更一般,匹配更多。

我没有说他不能,我说这不容易,而且使用ast比使用正则表达式更容易。我添加了一些示例代码,从那里他可以自己沿着节点走。你的新代码在
a,b=2,3
中找不到
b
。使用
ast.walk()
很难实现您正在尝试的内容,因为它不提供任何上下文。此外,我甚至不认为这是可取的——例如,如果在模块范围内的try/except块中有赋值(这是很常见的),为什么要排除发生在那里的赋值呢?我已经将您的想法合并到我的代码中,没有降序到类或函数定义中。Hmmm。。。说得好。我尝试了访客和步行,但两者都有相同的缺点。猜测
col\u offset==0
不是这样工作的。建议?否,
NodeVisitor
没有相同的缺点。我已经在我的代码中实现了基本思想。好的,我现在更喜欢你的代码;-)此外,它以块的形式打印赋值,如
if.\uuuuu name.\uuuuu==“\uuuuuuu main.\uuuuuu”:
@hochl:我的原始代码在函数中也包含赋值这一事实当然是一个有效的反对意见。:)我们现在已经完全分解了答案,OP似乎没有回到他的问题上来^^谢谢你们的回答。我想没有办法使用正则表达式来完成我需要的工作,因为使用建议的解决方案“^([\w\s,]+)=”获得的结果需要更多的工作才能在列表中很好地获得变量名。我将查看ast方法是否与正则表达式方法一样快;-)
^([\w\s,]+)=