Вот простой (и немного примитивный ;-) способ отследить «кто что пытается импортировать» в терминах имен модулей:
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
, который дает, например (сохранив это как 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__
Как видите, одна особенность "обертывания" встроенного __import__
заключается в том, что он не будет заглушен тем фактом, что импортируемый модуль уже находится в sys.modules
: поскольку забота об этом В одном из заданий __import__
наша оболочка вызывается для обоих модулей, «загружаемых в первый раз», и , которые просто собираются получить из sys.modules
, потому что они уже были импортированы ранее. Это должно пригодиться, когда вы пытаетесь диагностировать циклический импорт (все сводится к поиску циклов в ориентированном графе, ребра которого идентифицируются двумя именами модулей - импортированным и импортирующим), которые этот простой подход печатает на каждом выходная строка).