python - 如何在模块中以文本方式查找导入的名称

标签 python regex python-2.7

我写了一个方法叫buildRegex给定一个名称(类型为 str ),返回一个 regex找到 from ... import ... name 的对象Python 中的声明模块。

例如,这是 buildRegex 的预期行为:

>>> regObj = buildRegex('foo')
>>> regObj.search('from a import fool') is None
True
>>> regObj.search('from a import foo') is not None
True
>>> regObj.search('from a.b.c import foo as food') is None
True
>>> regObj.search('from a.b.c import fool, bar as foo') is not None
True

到目前为止,我所拥有的适用于上述所有示例(以及更多):

def buildRegex(name):
    singleImportedName = r'(\b{0}\b(?!\s+as\s+))'.format(name)
    importStatement = r'from\s+(\w+(\.\w+)*)\s+import\s+([^#\n]*)(?={0})'.format(singleImportedName )
    return re.compile(importStatement)

buildRegex假设搜索到的模块没有 SyntaxError这没关系。

我的问题是,在查找导入名称时 foo ,我还需要知道它是否是其他名称的别名。 IE。如果一个模块有语句:

from a.b.c import bar as foo

我想知道什么foo是别名,在这种情况下,这将是 bar .目前,由于 asserted lookaheads在正则表达式中,这是不可能的。所以,最后我的问题是: 我如何重构正则表达式以使此信息不丢失,即,如果给定名称是别名,则其别名的名称位于 regex 之一。的 groups

最佳答案

我建议不要编写复杂的正则表达式来解析导入,而是实际使用 ast.parse 将源代码解析为抽象语法树并从那里找到名称,如ast.parse 保证正确解析 Python。像这样的东西:

import ast

class ImportFinder(ast.NodeVisitor):
    def __init__(self):
        self.imports = []

    def visit_Import(self, node):
        names = []
        for i in node.names:
            names.append((i.name, i.asname))
        self.imports.append(['import', names])

    def visit_ImportFrom(self, node):
        module = node.module
        level = node.level  # how many dots
        names = []
        for i in node.names:
            names.append((i.name, i.asname))

        self.imports.append(('from', level, module, names))

def parse_imports(source):
    tree = ast.parse(source)
    finder = ImportFinder()
    finder.visit(tree)
    return finder.imports

示例用法:

import pprint

pprint.pprint(parse_imports('''
from foo import bar, baz, frob
from .. import bar as spam, baz as ham, frob
import bar.baz
import bar.foo as baf
'''))

打印出来:

[('from', 0, 'foo', [('bar', None), ('baz', None), ('frob', None)]),
 ('from', 2, None, [('bar', 'spam'), ('baz', 'ham'), ('frob', None)]),
 ['import', [('bar.baz', None)]],
 ['import', [('bar.foo', 'baf')]]]

from 行中的整数给出了模块名称前的 . 的编号。

关于python - 如何在模块中以文本方式查找导入的名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30037326/

相关文章:

python - 如何在删除每个字典的子集时合并成对的字典

python - 我可以对文件名使用 MD5 或 SHA1 哈希吗?

python - 在python中跨文件设置全局变量

python - 无法使用 Mechanize 找到表格

python - 重新采样每日数据以获得每月数据框?

python - nginx 拦截 google oauth 重定向

javascript - 扩展正则表达式以捕获多个条件

javascript - 替换字符串中的管道

javascript - 我正在尝试使用正则表达式来验证 javascript 中的电话号码

python - 如何继承异常来创建更具体的错误?