10

If I import a module, the module name shows up in both sys.modules and globals(). If I again delete it, it is removed from globals(), but still resides in sys.modules. Why is it so?

import mymodule
'mymodule' in globals()   # True
'mymodule' in sys.modules # True
del mymodule
'mymodule' in globals()   # False
'mymodule' in sys.modules # Still True, why?

I also found the following difference:

from mypackage import mymodule
'mypackage' in sys.modules            # True
'mymodule'  in sys.modules            # False !
'mypackage.mymodule' in sys.modules   # also True !

while the answers are complementary for globals():

'mypackage' in sys.modules            # False
'mymodule'  in sys.modules            # True 
'mypackage.mymodule' in sys.modules   # False
HongboZhu
  • 4,442
  • 3
  • 27
  • 33

3 Answers3

4

Just like any other Python object, a module continues to exist until there are no more references to it. In other words, sys.modules behaves like a regular dict, and

import mymodule
lst = {mymodule.__name__: mymodule}
'mymodule' in globals()   # True
'mymodule' in lst         # True
del mymodule
'mymodule' in globals()   # False
'mymodule' in lst         # Still True

sys.modules is only consulted on import statements. You can delete a module from sys.modules to make Python reload it the next time it is imported.

phihag
  • 278,196
  • 72
  • 453
  • 469
4

del removes the binding of a name in the appropriate scope; it has nothing to do with modules per se.

sys.modules keeps a list of all modules that have been loaded, regardless of whether they're bound to any name in your program.

Wooble
  • 87,717
  • 12
  • 108
  • 131
3

Because Python caches modules in sys.modules to prevent the (expensive, slow) module-finding process being run more than is necessary.

It is OK to remove the module from sys.modules if you need to, although reload may also work.


In more detail, when you import mymodule various things happen. Off the top of my head, and assuming mymodule isn't one of the modules built in to the interpreter executable:

  1. The interpreter runs some complex code to locate the file containing mymodule (this may be mymodule.py, mymodule.pyc, or mymodule.pyd -- or maybe something else that I haven't thought of. This looks through the current directory, sys.path, and other places too.

  2. The file thus located is lexed, parsed, and compiled (if necessary) into interpreter bytecodes.

  3. The compiled module is executed, giving a module object.

  4. The module object is inserted into sys.modules.

  5. The module object is bound to the local variable specified in the import statement.

(The above is a very rough approximation based on what I remember about the mechanics behind import. It's probably wrong in important and subtle ways.)

Note, then, that binding the module object to the local name is actually quite a small part of the actual import process. Removing the name binding, by executing del mymodule, doesn't affect the rest of the import.

Katriel
  • 120,462
  • 19
  • 136
  • 170
  • 1
    But if I delete the name binding by executing `del mymodule`, I remove it from the namespace so I can execute `import mymodule` and these two steps together is equivalent to execute `reload(mymodule)`, right? – HongboZhu Aug 19 '11 at 13:17
  • 1
    @Hongbo: wrong: `import` looks first in `sys.modules` to see whether it has already imported the module. If it has, it will just give you the module object that it made when it last imported the module. Since `del mymodule` doesn't remove the module object from `sys.modules`, re-importing it will just rebind the name to the object in `sys.modules`. – Katriel Aug 19 '11 at 13:19
  • 1
    @Hongbo: if you want it to re-import the module, do `reload(module)`. Equivalently, delete it from `sys.modules` and then `import` it. – Katriel Aug 19 '11 at 13:21
  • 1
    Many thanks, katrielalex. Your answer helped me solve the puzzle in the post [module name in sys.modules and globals()](http://stackoverflow.com/questions/6946376/how-to-reload-a-class-in-python-shell) – HongboZhu Aug 19 '11 at 14:36