Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do something every time a module is imported

Tags:

python

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?

like image 668
andyortlieb Avatar asked Feb 08 '13 17:02

andyortlieb


People also ask

What happens when a module is imported?

When a module is first imported, Python searches for the module and if found, it creates a module object 1, initializing it. If the named module cannot be found, a ModuleNotFoundError is raised. Python implements various strategies to search for the named module when the import machinery is invoked.

How many times does a module get loaded when imported multiple times?

The rules are quite simple: the same module is evaluated only once, in other words, the module-level scope is executed just once. If the module, once evaluated, is imported again, it's second evaluation is skipped and the resolved already exports are used.

Does importing a module run it?

Summary. When you import a module, Python will run all the code that's in that module. So if your Python file is meant to be imported as a module, be careful not to put side effects at the top-level of your . py file.

When a module is imported for the first time then?

A module code is evaluated only the first time when imported. If the same module is imported into multiple other modules, its code is executed only once, upon the first import. Then its exports are given to all further importers. The one-time evaluation has important consequences, that we should be aware of.


1 Answers

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.

like image 96
mgibsonbr Avatar answered Oct 15 '22 18:10

mgibsonbr