Here's a simple (and slightly rudimentary;-) way to trace "who's trying to import what" in terms of module names:
import inspect
import __builtin__
savimp = __builtin__.__import__
def newimp(name, *x):
caller = inspect.currentframe().f_back
print name, caller.f_globals.get('__name__')
return savimp(name, *x)
__builtin__.__import__ = newimp
which gives, for example (having saved this as tracimp.py
):
$ python -c 'import tracimp; import email; import sys; import email.mime'
email __main__
sys email
email.mime email
sys __main__
email.mime __main__
As you see, one specific characteristic of "wrapping" the __import__
built-in is that it won't be silenced by the fact that a module being imported is already in sys.modules
: since taking care of that is one of __import__
's jobs, our wrapper gets called for both modules "being loaded for the first time" and ones that are just going to get fetched from sys.modules
because they were already imported previously. This should come in really handy when you're trying to diagnose circular imports (it boils down to finding loops in the directed graph whose edges are identified by the two module names -- imported and importer -- which this simple approach is printing on each output line).