我已接近我的最终目标,即在模块和其他导入的模块之间生成一个漂亮的图形。
例如,如果x从y和z导入,y从t和v导入,我希望:
x -> y, z
y -> t, v
现在我已经将导入钩子定义如下,但是在一个简单的文件上运行它我得不到我期望的结果:
python study_imports.py CollectImports simple.py
('study_imports.py', 'study_imports')
simple.py实际上是从study_imports导入的。 问题是我想看“simple.py”而不是“study_imports.py”,有没有办法让文件的路径实际导入其他模块?
class CollectImports(object):
"""
Import hook, adds each import request to the loaded set and dumps
them to file
"""
def __init__(self, output_file):
self.loaded = set()
self.output_file = output_file
def __str__(self):
return str(self.loaded)
def cleanup(self):
"""Dump the loaded set to file
"""
dumped_str = '\n'.join(x for x in self.loaded)
open(self.output_file, 'w').write(dumped_str)
def find_module(self, module_name, package=None):
#TODO: try to find the name of the package which is actually
#importing something else, and how it's doing it
#use a defualtdict with empty sets as the storage for this job
entry = (__file__, module_name)
self.loaded.add(str(entry))
答案 0 :(得分:2)
可能使用inspect模块。
模块a.py
import inspect
print inspect.stack()
模块b.py
import a
运行b.py时,我得到了:
[
(<frame object at 0x28a9b70>, '/path/a.py', 5, '<module>', ['print inspect.stack()\n'], 0),
(<frame object at 0x28a9660>, 'b.py', 2, '<module>', ['import to_import\n'], 0)
]
看起来第二帧包含您需要的内容。
答案 1 :(得分:1)
所以我更好地看了一下snakefood,最后我用AST重写了我的代码。 Snakefood仍然使用编译器,它被弃用并且比使用ast慢得多。
结果很棒,例如这是访问者:
from ast import parse, NodeVisitor
class ImportVisitor(NodeVisitor):
def __init__(self):
self.imported = set()
super(ImportVisitor, self).__init__()
def __str__(self):
return '\n'.join(x for x in self.imported)
def visit_Import(self, node):
for n in node.names:
self.imported.add(n.name)
#that we are using
def visit_ImportFrom(self, node):
self.imported.add(node.module)
可以使用例如:
def gen_module_imports(mod):
try:
at = parse(open(mod).read())
except SyntaxError:
print("file %s has a syntax error, please fix it" % mod)
return []
else:
v = ImportVisitor()
v.visit(at)
return v.imported
答案 2 :(得分:0)
检查技巧似乎工作得很好:) 我在imports.log中得到了类似simple.py:set(['study_imports'])的内容。
Class CollectImports(object):
"""
Import hook, adds each import request to the loaded set and dumps
them to file
"""
def __init__(self, output_file):
self.loaded = defaultdict(lambda: set())
self.output_file = output_file
def __str__(self):
return str(self.loaded)
def cleanup(self):
"""Dump the loaded set to file
"""
dumped_str = '\n'.join(('%s: %s' % (k, v)) for k, v in self.loaded.items())
open(self.output_file, 'w').write(dumped_str)
def find_module(self, module_name, package=None):
st = inspect.stack()
self.loaded[st[1][1]].add(module_name)