This is another post based on Dr. Fred Baptiste’ Python 3: Deep Dive series. For more, head over to Udemy.
What happens behind the scenes in a python import
statement? Glad I asked. Here’s how it works:
- Check
sys.modules
: Python first checkssys.modules
to see if your module has already been loaded.-
sys.modules
is a regular pythondict
that is used to cache modules. The keys are strings of the modules’ names and the values are module objects (i.e. objects of typeModuleType
) - If your module is already in
sys.modules
, python adds the cached version toglobals()
and skips the steps below.
-
- Create a module object: If python does not find the module in
sys.modules
, it creates a newModuleType
object and loads the module’s source code into it - Cache the module: The new
module
objects is added to thesys.modules
cache - Compile and execute: Python compiles and executes the source code from your module
- Add to
globals()
: Python and adds your module toglobals()
, making it available for use going forward.
Key Point: It is often said that importing a python module will execute all of the code in the module. That is only partly true. Python only executes a module the first time it is imported, then caches it in sys.modules
. Subsequent import
statements throughout your code, even in different files, will refer back to the cached version and will not execute the module again.
Below is a bit of code to bring all of this home. We will:
- Create a simple module (
module1
) with a print statement so we can see when the module gets executed. - Import
module1
intomain.py
, which will executemodule1
. - Delete
module1
fromglobals()
, then try accessing it to demonstrate that it is no longer available. - Re-import
module1
. This will addmodule1
back toglobals()
, but will use the cached version fromsys.modules
and will not re-executemodule1
. - Access
module1
again to demonstrate that is has in fact been added back toglobals()
<span># module1.py </span><span>print</span><span>(</span><span>"</span><span>Running module1</span><span>"</span><span>)</span><span># main.py </span><span>print</span><span>(</span><span>"</span><span>======== Running main.py ======== </span><span>"</span><span>)</span><span>print</span><span>(</span><span>"</span><span>Importing module1</span><span>"</span><span>)</span><span>import</span> <span>module1</span><span>print</span><span>(</span><span>"</span><span>Deleting module1</span><span>"</span><span>)</span><span>del</span> <span>globals</span><span>()[</span><span>"</span><span>module1</span><span>"</span><span>]</span> <span># Deletes from globals(), but not from sys.modules </span><span>try</span><span>:</span><span>print</span><span>(</span><span>"</span><span>Accessing module 1 after deleting from globals()</span><span>"</span><span>)</span><span># This will cause an exception. module1 is still cached in `sys.modules`, </span> <span># but the reference to the cache has been removed from globals() </span> <span>module1</span><span>except</span> <span>NameError</span> <span>as</span> <span>e</span><span>:</span><span>print</span><span>(</span><span>"</span><span>NameError</span><span>"</span><span>,</span> <span>e</span><span>)</span><span>print</span><span>(</span><span>"</span><span>Re-importing module1</span><span>"</span><span>)</span><span># Adds the cached version of module1 back to globals(), without # re-executing the module </span><span>import</span> <span>module1</span><span>print</span><span>(</span><span>"</span><span>Accessing module 1 after re-importing from globals()</span><span>"</span><span>)</span><span>module1</span><span>print</span><span>(</span><span>"</span><span>Done!</span><span>"</span><span>)</span><span>print</span><span>(</span><span>"</span><span>=================================</span><span>"</span><span>)</span><span># module1.py </span><span>print</span><span>(</span><span>"</span><span>Running module1</span><span>"</span><span>)</span> <span># main.py </span><span>print</span><span>(</span><span>"</span><span>======== Running main.py ======== </span><span>"</span><span>)</span> <span>print</span><span>(</span><span>"</span><span>Importing module1</span><span>"</span><span>)</span> <span>import</span> <span>module1</span> <span>print</span><span>(</span><span>"</span><span>Deleting module1</span><span>"</span><span>)</span> <span>del</span> <span>globals</span><span>()[</span><span>"</span><span>module1</span><span>"</span><span>]</span> <span># Deletes from globals(), but not from sys.modules </span><span>try</span><span>:</span> <span>print</span><span>(</span><span>"</span><span>Accessing module 1 after deleting from globals()</span><span>"</span><span>)</span> <span># This will cause an exception. module1 is still cached in `sys.modules`, </span> <span># but the reference to the cache has been removed from globals() </span> <span>module1</span> <span>except</span> <span>NameError</span> <span>as</span> <span>e</span><span>:</span> <span>print</span><span>(</span><span>"</span><span>NameError</span><span>"</span><span>,</span> <span>e</span><span>)</span> <span>print</span><span>(</span><span>"</span><span>Re-importing module1</span><span>"</span><span>)</span> <span># Adds the cached version of module1 back to globals(), without # re-executing the module </span><span>import</span> <span>module1</span> <span>print</span><span>(</span><span>"</span><span>Accessing module 1 after re-importing from globals()</span><span>"</span><span>)</span> <span>module1</span> <span>print</span><span>(</span><span>"</span><span>Done!</span><span>"</span><span>)</span> <span>print</span><span>(</span><span>"</span><span>=================================</span><span>"</span><span>)</span># module1.py print("Running module1") # main.py print("======== Running main.py ======== ") print("Importing module1") import module1 print("Deleting module1") del globals()["module1"] # Deletes from globals(), but not from sys.modules try: print("Accessing module 1 after deleting from globals()") # This will cause an exception. module1 is still cached in `sys.modules`, # but the reference to the cache has been removed from globals() module1 except NameError as e: print("NameError", e) print("Re-importing module1") # Adds the cached version of module1 back to globals(), without # re-executing the module import module1 print("Accessing module 1 after re-importing from globals()") module1 print("Done!") print("=================================")
Enter fullscreen mode Exit fullscreen mode
Output from main.py:
======== Running main.py ========Importing module1Running module1Deleting module1Accessing module 1 after deleting from globals()NameError name 'module1' is not definedRe-importing module1Accessing module 1 after re-importing from globals()Done!========================================= Running main.py ======== Importing module1 Running module1 Deleting module1 Accessing module 1 after deleting from globals() NameError name 'module1' is not defined Re-importing module1 Accessing module 1 after re-importing from globals() Done! ========================================= Running main.py ======== Importing module1 Running module1 Deleting module1 Accessing module 1 after deleting from globals() NameError name 'module1' is not defined Re-importing module1 Accessing module 1 after re-importing from globals() Done! =================================
Enter fullscreen mode Exit fullscreen mode
暂无评论内容