如何在模块中以文本方式查找导入的名称
我编写了一个方法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
的群体?
-
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)