Summary: in this tutorial, you will examine the Python import statement variants and how they work under the hood.
import module
When you import a module, Python does two things:
- First, check if the module has been loaded and cached in the sys.modules. If not, it will execute the module and create a reference to the module object.
- Second, add the module name to the global namespace referencing the same module object.
The following program imports the math module and prints out the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 object in thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)1 and global namespace:import sys import math print('sys.modules:', hex(id(sys.modules['math']))) if 'math' in globals(): print('globals: ', hex(id(globals()['math'])))
Code language: JavaScript (javascript)Output:
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)As you can see, the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 variable references the same module object.If you import a module for the second time, Python does not execute the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 module again but gets it from thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)1 cache.from module import object
When you import an object (a function, a class, etc., ) from a module, Python does the following:
- First, check if the module has been loaded and cached in the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)1. If not, it will execute the module and create a reference to the module object. - Second, add the import object to the global namespace.
In this case, Python does not add a variable that references the module to the global namespace but a variable that references the imported object.
The following example imports the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)6 function from thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 object:import sys from pprint import pprint from math import ceil print('sys.modules:', hex(id(sys.modules['math']))) pprint(globals())
Code language: JavaScript (javascript)Output:
sys.modules: 0x11d659c2130 {'__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, '__doc__': None, '__file__': 'C:/oop/app.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000011D65A008E0>, '__name__': '__main__', '__package__': None, '__spec__': None, 'ceil': <built-in function ceil>, 'pprint': <function pprint at 0x0000011D661C4040>, 'sys': <module 'sys' (built-in)>}
Code language: PHP (php)In this example, Python loads the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 module into thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)1. However, it only creates a reference to thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)6 function, not thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 module object in the global namespace.from module import object as object_alias
When you load an object from a module and use an alias, Python will do the following:
- First, check if the module has been loaded and cached in the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)1. If not, it will execute the module and create a reference to the module object. - Second, create an alias that references the imported object and add it to the global namespace.
For example, the following imports the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)6 function from the math module and use the ceiling alias:import sys from math import ceil as ceiling print('sys.modules:', hex(id(sys.modules['math']))) print('globals:', hex(id(globals()['ceiling'])))
Code language: JavaScript (javascript)Output:
sys.modules: 0x1cc4f244ae0 {'__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, '__doc__': None, '__file__': 'C:/oop/app.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001CC4EA708E0>, '__name__': '__main__', '__package__': None, '__spec__': None, 'ceiling': <built-in function ceil>, 'pprint': <function pprint at 0x000001CC4F234040>, 'sys': <module 'sys' (built-in)>}
Code language: PHP (php)from module import *
When you import everything from a module, Python will do the following:
- First, check if the module has been loaded and cached in the sys.modules. If not, it will execute the module and create a reference to the module object.
- Second, add all symbols from the module to the global namespace.
For example, the following imports all the objects from the math module:
import sys from pprint import pprint from math import * print('sys.modules:', hex(id(sys.modules['math']))) pprint(globals())
Code language: JavaScript (javascript)Output:
sys.modules: 0x1e1ebf24b30 {'__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, '__doc__': None, '__file__': 'C:/oop/app.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001E1EB7408E0>, '__name__': '__main__', '__package__': None, '__spec__': None, 'acos': <built-in function acos>, 'acosh': <built-in function acosh>, 'asin': <built-in function asin>, .... 'tau': 6.283185307179586, 'trunc': <built-in function trunc>}
Code language: PHP (php)As you can see clearly from the output, Python adds all the functions from the math module to global namespaces. In this case, if any symbols exist in the global namespace, Python will replace their references.
This often leads to bugs that are difficult to track. Therefore, you should avoid using the from module import *
Python import misconception
One of the most common misconceptions of the import statement is that many consider the following statement:
from math import ceil
Code language: JavaScript (javascript)is more efficient than:
import math
Code language: JavaScript (javascript)Because the first statement imports only the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)6 function while the second statement imports the wholesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 module.However, Python loads the whole
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 module in both cases.The first statement creates a symbol that references the
sys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)6 function from thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 module while the second statement creates thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 symbol that references thesys.modules: 0x20456766590 globals: 0x20456766590
Code language: HTTP (http)0 module object.