This article details Python's import mechanism, which is helpful for understanding Python's operating mechanism.
1. Standard Import:
All modules loaded into memory in Python are placed in sys.modules. When you import a module, you first look in this list to see if the module has already been loaded, and if it does, just add the name of the module to the local namespace of the module that is calling import. If not loaded, the module file is searched from the Sys.path directory according to the module name, the module can be py, PYC, PYD, the module is loaded into memory after it is found, added to the Sys.modules, and the name is imported into the current local namespace.
A module does not repeat loading. Many different modules can be imported into the same module with the local name space, in fact, behind the Pymoduleobject object only one. Here's an easy to ignore problem: Import only imports modules and cannot import objects (classes, functions, variables, and so on) in the module. For example, there is a function getName in module A (a.py), and another module cannot import getName into this module through import a.getname, only from import getName.
2. Nested import:
1) Sequential nesting
For example: This module imports a module (import a), A and import b,b modules can import other modules ...
This nesting is easy to understand and one thing to note is that each module's local namespace is independent. For the above example, after import a of this module, this module can only access module A and cannot access module B and other modules. Although module B is already loaded into memory, if the access is further explicit in this module, import B.
2) Loop nesting
For example:
file [a.py]
From B import D
class C:pass
file [b.py]
From A import C
class D:pass
Why can't I load D when I execute a?
If you change the a.py to: Import B is OK.
What the hell is going on here?
Robertchen: This is related to the mechanism of the internal import of Python, which is divided into several steps within the From B import D,python:
(1) Find the symbol "B" in Sys.modules
(2) If symbol B exists, the module object corresponding to symbol B is obtained.
Obtain the object corresponding to the symbol "D" from the __dict__ of <modult b>, and throw an exception if "D" does not exist.
(3) If symbol B does not exist, create a new module object <module B>, note that at this point, the __dict__ of the module object is empty.
Executes the expression in b.py to fill the __dict__ of the <module b>.
Obtain the object corresponding to "D" from the __dict__ of <module b>, and throw an exception if "D" does not exist.
So this example is executed in the following order:
1, the implementation of a.py from B import D because it is an executing Python a.py, so there is no <module b> presence in Sys.modules, first create a Module object for b.py (<mod Ule b>), note that the module object created at this time is empty, with nothing inside, and after creating the module object inside Python, the execution b.py is parsed to fill <module b> this __dict__.
2, in the execution of the b.py from import C in the execution of b.py process, will encounter this sentence, first check sys.modules This module cache is already exists <module a>, because the cache has not yet cached < module A> So similarly, Python internally creates a Module object (<module a>) for a.py, and then, similarly, executes the statements in the a.py
3. Execute a.py from B import D at this point, the <module b> object that was created in the 1th step is already slow to exist in the sys.modules, so the <module B> is obtained directly; From the whole process, we know that when <module b> is still an empty object, there is nothing in it, so getting the symbol "D" from this module throws an exception. If this is just import B, the symbol "B" already exists in the sys.modules, so it does not throw an exception.
ZQ: The diagram is as follows:
3. Package Import
as long as there is a __init__.py file underneath a folder, the folder can be considered a package. The process of package import and module is basically consistent, only when importing the package will execute the __init__.py in this package directory instead of the statement inside the module. In addition, if you are simply importing a package and there is no explicit other initialization in the package's __init__.py, the module below this package will not be imported automatically.
For example:
The following package structure is available:
Pa
|----__init__.py
|----wave.py
|----PB1
|----__init__.py
|----pb1_m.py
|----PB2
|----__init__.py
|----pb2_m.py
The following procedures are available:
Import sys
import pa.wave #1
import PA. PB1 #2
import PA. Pb1.pb1_m as M1 #3
import PA. Pb2.pb2_m #4
PA.wave.getName () #5
m1.getname () #6
PA. PB.pb2_m.getName () #7
1) When the #1 is executed, Sys.modules will have both the PA and Pa.wave two modules, at which point any class or function of Pa.wave can be invoked. But you cannot call PA. Any module under PB1 (2). There is a PA name in the current local.
2) When the #2 is executed, just the PA. PB1 loaded into memory, Sys.modules will have PA, Pa.wave, Pa. PB1 three modules, but PA. Any modules under PB1 are not automatically loaded into memory, at which point if the PA is executed directly. PB1.pb1_m.getName () can be faulted because the PA. There is no pb1_m in the PB1. The current local is still only the PA name, and there is no PA. PB1 name.
3) When the #3 is executed, the PA. PB1 under the pb1_m load memory, Sys.modules will have PA, Pa.wave, Pa. PB1, PA. Pb1.pb1_m four modules, the PA can be executed at this time. PB1.pb1_m.getName (). Because of the use of as, the current local in addition to the PA name, added M1 as Pa. Alias for Pb1.pb1_m.
4) When the #4 is executed, the PA. PB2, PA. Pb2.pb2_m loaded into memory, Sys.modules will have PA, Pa.wave, Pa. PB1, PA. Pb1.pb1_m, PA. PB2, PA. Pb2.pb2_m six modules. Current local or only PA, M1.
The #5 below, #6, #7 can run correctly.
Note: if the PA. Pb2.pb2_m want to import PA. Pb1.pb1_m, Pa.wave can be directly successful. It is best to adopt an explicit import path for./. Relative import path is still not recommended.