2011-11-23 61 views
1

我正在接近我的最终目标,即在模块和其他导入的模块之间生成一个很好的图形。生成导入图表

例如,如果从T中y和z,和y的进口X进口和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)) 
+2

你知道的[Snakefood的'sfood-graph']( http://furius.ca/snakefood/doc/snakefood-doc.html#seconds-usage-instructions)? –

+0

我现在非常感谢,这是非常好的,但我仍然想让我的版本工作,只是为了理解.. –

回答

2

也许与inspect模块。

模块a.py运行b.py时

import inspect 

print inspect.stack() 

模块b.py

import a 

,我得到:

[ 
    (<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) 
] 

看起来像第二帧包含你需要。

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) 
0

所以我看了一眼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) 

哪些可以USEF例如为:

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