孤立したモジュールを見つける

いつの間にか何所からも使われなくなったモジュールを探すスクリプトです。

自作アプリ"sffairmaker"の中から探します。

python -m sffairmaker.main

を実行すると、アプリが動くようになっているので、
"C:\\Python26\\Lib\\site-packages\\sffairmaker\\main.py"を起点にして探索しています。

#encoding:shift-jis
#solitary_module_finder.py
from __future__ import division, print_function
__metaclass__ = type 

import sys
from os.path import *
import os
from modulefinder import ModuleFinder
from collections import defaultdict

class DependencyFinder(ModuleFinder):
    def __init__(self, *a, **kw):
        self.dependency = defaultdict(set)
        self._last_caller = None
        ModuleFinder.__init__(self, *a, **kw)
    
    def import_hook(self, name, caller=None, fromlist=None, level=None):
        old_last_caller = self._last_caller
        try:
            self._last_caller = caller
            return ModuleFinder.import_hook(self, name, caller, fromlist, level)
        finally:
            self._last_caller = old_last_caller
    
    def import_module(self, *a, **kw):
        module = ModuleFinder.import_module(self, *a, **kw)
        if module is not None:
            self.dependency[module.__name__].add(self._last_caller.__name__)
        return module
    
def main():
    ## {package}\main.py が実行されたときにimportされるモジュールを集めます。
    finder = DependencyFinder()
    package = "C:\Python26\Lib\site-packages\\sffairmaker"
    finder.run_script(join(package, "main.py"))
    
    ## {package}の直下にあるモジュールで、importされていないものを出力します。
    for name in os.listdir(package):
        if isfile(join(package, name)) and name.endswith(".py"):
            modname = "sffairmaker." + name[:-3]
            if not finder.dependency[modname]:
                print(modname)
    
if "__main__" == __name__:
    main()

実行結果:

$>solitary_module_finder.py
sffairmaker.main
sffairmaker.__init__

__init__はパッケージである事を示すための空のファイル、mainはアプリ起動するだけで他から呼び出されないモジュールなので、孤立しているモジュールが無いことが分かりました。


ちなみに、上のコードはhttp://www.tarind.com/depgraph.htmlのpy2depgraph.pyをパクッタものですが、かのページにはモジュール同士の依存関係をグラフにして出力するスクリプトが置いてあります。ためしにsffairmakerを調べてみたら、9845 x 3547 Pixelsの巨大な画像に・・・。実際に使うときは標準モジュールを外すなどの改造をしてから使った方が良さそうです、