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

发布于 2021-01-29 15:03:08

我编写了一个方法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,我还需要知道它是否是其他名称的别名。即模块是否具有以下语句:

from a.b.c import bar as foo

我想知道什么foo是混叠,在这种情况下就是bar。当前,由于asserted lookaheads正则表达式,这是不可能的。所以,最后我的问题:我如何重构,使该信息不丢失,正则表达式,即,如果给定的名称是别名,则名称的别名是在一个regex群体

关注者
0
被浏览
74
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。
    import inspect
    import importlib
    import ast
    
    
    class Imports(ast.NodeVisitor):
        def visit_Import(self, node):
            print("In Import")
            for imp in node.names:
                if imp.asname is not None:
                    print("module name = {}, alias = {}".format(imp.name, imp.asname))
                else:
                    print("module name = {}".format(imp.name))
            print()
    
        def visit_ImportFrom(self, node):
            print("In ImportFrom")
            for imp in node.names:
                if imp.asname is not None:
                    print("module = {}\nname = {}\nalias = {}\nlevel = {}\n".
                          format(node.module, imp.name, imp.asname, node.level))
                else:
                    print("module = {}\nname = {}\nlevel = {}\n".
                          format(node.module, imp.name, node.level))
            print()
    
    mod = "temp_test"
    mod = importlib.import_module(mod)
    p = ast.parse(inspect.getsource(mod))
    Imports().visit(p)
    

    输入:

    from bisect import bisect_left as bs
    import datetime
    import time
    import numpy as np
    
    def foo():
        from re import findall
    
    class Foo():
        def test(self):
            from re import compile as cp, finditer as ft
    

    输出:

    In ImportFrom
    module = bisect
    name = bisect_left
    alias = bs
    level = 0
    
    
    In Import
    module name = datetime
    
    In Import
    module name = time
    
    In Import
    module name = numpy, alias = np
    
    In ImportFrom
    module = re
    name = findall
    level = 0
    
    
    In ImportFrom
    module = re
    name = compile
    alias = cp
    level = 0
    
    module = re
    name = finditer
    alias = ft
    level = 0
    

    类Import(名称)

    导入声明。名称是别名节点的列表。

    ImportFrom类(模块,名称,级别)

    从x导入y表示。module是“
    from”名称的原始字符串,没有任何前导点,对于诸如from的语句则为None。导入foo。level是一个保持相对导入级别的整数(0表示绝对导入)。

    greentreesnakes至少文档,我有什么样的所有节点做一个更好的解释,以及如何使用AST模块比实际AST文档本身。

    您还可以使用直接传递模块或打开py文件并将内容传递给ast.parse:

    with open("temp_test.py") as f:
        p = ast.parse(f.read(), filename="<ast>", mode="exec")
    Imports().visit(p)
    

    并传递模块:

    import  temp_test
    
    p = ast.parse(inspect.getsource(temp_test))
    Imports().visit(p)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看