6

Is there a way to do something (like print "funkymodule imported" for example) every time a module is imported from any other module? Not only the first time it's imported to the runtime or reloaded?

asked Feb 8, 2013 at 17:49
7
  • 1
    Why would you want to import a module that's already been imported? Commented Feb 8, 2013 at 17:51
  • 1
    This probably isn't possible. PEP-396 describes such a mechanism, but was withdrawn. Commented Feb 8, 2013 at 17:52
  • 1
    The only way I can think of is to replace sys.modules with a custom mapping, reimplementing __getitem__, but the import machinery probably calls directly PyDict_GetItem from the C side so even this shouldn't work. Commented Feb 8, 2013 at 17:54
  • 1
    You can do this much more easily with grep... Commented Feb 8, 2013 at 18:13
  • 2
    Once I ran into a problem of cyclic dependencies - module A was importing module B, that in turn was importing A again before A was ready. That was pretty hard to debug, and I ended up using something like this. In my case at least, using grep wouldn't be enough - since I was not only interested in how many times the import happened, but in their order as well (and I didn't know which modules were problematic). Thus I think it's an interesting question, although not something I'd do in production code. Commented Feb 8, 2013 at 18:27

1 Answer 1

9

One possibility would be to monkey patch __import__:

>>> old_import = __import__
>>> def my_import(module,*args,**kwargs):
... print module, 'loaded'
... return old_import(module,*args,**kwargs)
...
>>> __builtins__.__import__ = my_import
>>> import datetime
datetime loaded
>>> import datetime
datetime loaded
>>> import django
django loaded

It worked fine on command line (using Python 2.7.3 on Windows XP), but I dunno if would work in other environments.

To access the module object (instead of just the module name - so you can do something useful with it) just intercept the return value instead of the argument:

>>> def my_import(*args,**kwargs):
... ret = old_import(*args,**kwargs)
... print ret
... return ret
...
>>> __builtins__.__import__ = my_import
>>> import datetime
<module 'datetime' (built-in)>
>>> import django
<module 'django' from 'C:\Python27\lib\site-packages\django\__init__.pyc'>

Update: Just confirmed it works if used inside a python file too - though in this case, the correct way of assigning it is __builtins__['__import__'] = my_import.

answered Feb 8, 2013 at 17:58
Sign up to request clarification or add additional context in comments.

4 Comments

I want to know every time module A gets imported from any other module. Not how many times module B is importing module A.
This code will be called every time a module is imported (using import module), no matter who is importing it. Even imports inside imports will work (though for the inner modules, only the first time will show it - since the module body is not run again).
It's a cool solution. I was hoping to find some way to avoid monkeypatching import, especially since there's only exactly one specific module that I care about tracking in this sense. But it could definitely get me what I need.
You could probably just do a return old_import(*args,**kwargs) at the end after whatever extra stuff you wanted done (unless you wanted to do something afterwards, of course).

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.