2011-11-23 59 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