How to prevent a module from being imported twice?

2019-01-11 17:11发布

问题:

When writing python modules, is there a way to prevent it being imported twice by the client codes? Just like the c/c++ header files do:

#ifndef XXX
#define XXX
...
#endif

Thanks very much!

回答1:

Python modules aren't imported multiple times. Just running import two times will not reload the module. If you want it to be reloaded, you have to use the reload statement. Here's a demo

foo.py is a module with the single line

print "I am being imported"

And here is a screen transcript of multiple import attempts.

   >>> import foo
   Hello, I am being imported
   >>> import foo # Will not print the statement
   >>> reload(foo) # Will print it again
   Hello, I am being imported


回答2:

Imports are cached, and only run once. Additional imports only cost the lookup time in sys.modules.



回答3:

As specified in other answers, Python generally doesn't reload a module when encountering a second import statement for it. Instead, it returns its cached version from sys.modules without executing any of its code.

However there are several pitfalls worth noting:

  • Importing the main module as an ordinary module effectively creates two instances of the same module under different names.

    This occurs because during program startup the main module is set up with the name __main__. Thus, when importing it as an ordinary module, Python doesn't detect it in sys.modules and imports it again, but with its proper name the second time around.

    Consider the file /tmp/a.py with the following content:

    # /tmp/a.py
    import sys
    
    print "%s executing as %s, recognized as %s in sys.modules" % (__file__, __name__, sys.modules[__name__])
    import b
    

    Another file /tmp/b.py has a single import statement for a.py (import a).
    Executing /tmp/a.py results in the following output:

    root@machine:/tmp$ python a.py
    a.py executing as __main__, recognized as <module '__main__' from 'a.py'> in sys.modules
    /tmp/a.pyc executing as a, recognized as <module 'a' from '/tmp/a.pyc'> in sys.modules
    

    Therefore, it is best to keep the main module fairly minimal and export most of its functionality to an external module, as advised here.

  • This answer specifies two more possible scenarios:

    1. Slightly different import statements utilizing different entries in sys.path leading to the same module.
    2. Attempting another import of a module after a previous one failed halfway through.