Signup/Sign In
LAST UPDATED: OCTOBER 10, 2019

Python import Statement

    You might have seen or written your own import statements while writing Python programs. Have you ever wondered about the mechanism behind the import statement? Wondered how it effortlessly fetches the packages you need and helps you use the functionalities present in those packages?

    If you haven't, its time you ponder over this question and continue reading this post to understand what actually happens when the import statement is executed.

    The process of gaining access to the code in module A and using it in module B is known as importing (that module A into environment module B). This is done with the help of the import statement.

    When an import statement is executed, (say import module_1) the built-in method __import__() is called.

    Note: It is not a hard and fast rule that only the __import__ method has to be called.

    Suppose, importlib.import_module() is used. Then, instead of calling the __import__ method, customized import methods are implemented.


    What if I call the __import__ method directly?

    This can be done, but it might lead to certain consequences, which include, but not limited to, import of parent packages, updating of different cache (this could include the sys.modules). In addition to this, the call to __import__ method will not bind the name of the module to the name in the local namespace. It only searches for the module and if the module is found, it creates a module object and initializes it. In case the module is not found, it raises a ModuleNotFoundError.

    Many techniques can be used to search for a module in Python, and these can be modified and customized according to the implementation requirements.

    Below is an example that shows what happens when a module is not found:

    import tensorflow

    Following will be the output,

    Traceback (most recent call last):
    
      File "<ipython-input-1-d6579f534729>", line 1, in <module>
        import tensorflow
    
    ModuleNotFoundError: No module named 'tensorflow'

    The import statement brings together two operations, i.e searching, and binding.

    The name of the module written after the import statement is searched for in that system, and the result of this search is integrated with a name in that local scope. During searching operation, the __import__ function is called by passing relevant parameters to it. Then a module object is created and initialized. The value returned by the __import__ function is used to bind it to the namespace in the local scope for that part of the code.


    Consider the below statement,

    import module_1, module_2

    This import statement is executed as if there were 2 import statements used to import the module_1 and module_2 separately. The modules are searched for, loaded, initialized and then bound with the local namespace like a reference.

    Suppose module_1 and module_2 are top-level modules, i.e they are both parent modules that contain many more methods and implemented functionalities, in such cases, the top-level module's name is bound with the local namespace, like a reference.

    In case module_1 and module_2 are not top-level modules, the parents (or top-level package) of these 2 modules are bound to the local namespace like a reference. In addition to this, the modules need to be accessed with the help of their parent module and the dot operator.

    For example,

    import numpy as np
    
    np.square()

    Numpy module has been imported with the alias name np and one of the methods present inside the np module is square. It is accessed using the dot operator by binding the parent module with the square method.


    Consider the below statement:

    import module_1 as m1

    Here the keyword as helps give an alias name to the module_1 and m1 is bound to the local namespace (which actually refers to module_1)


    Consider the below statement:

    from numpy import square

    When the from keyword is used, the module followed by the from keyword is searched for, loaded and initialized. Here the square method or attribute of the Numpy package needs to be accessed. Hence the square attribute is searched for in the module. If it is not found, a submodule with that same name is searched for, in which again the square attribute is searched for. If not found, an ImportError is raised. Otherwise, it is stored like a reference in the local namespace.


    Below is a demonstration of ImportError:

    from numpy import squar

    For the code above, we will get the following output:

    Traceback (most recent call last):
    
      File "<ipython-input-6-774fbf55d7b8>", line 1, in <module>
        from numpy import squar
    
    ImportError: cannot import name 'squar' from 'numpy' (C:\ProgramData\Anaconda3\lib\site-packages\numpy\__init__.py)

    Summary:

    import module_1: This statement binds module_1 to a local namespace.

    import module_1.module_2.module_3: This statement imports module_1.module_2.module_3 and binds module_1 with the local namespace like a reference and uses module_3.

    import module_1.module_2.module_3 as mod_one: This statement imports module_1.module_2.module_3 and binds mod_one to local namespace.

    from module_1.module_2 import module_3: This statement imports module_3 from module_1.module_2 and binds it to the local namespace

    from module_1 import attr_1: This statement imports attr_1 from the module module_1 and binds it to the local namespace.


    Conclusion

    In this post, we understood how the import statement could be used to import modules and the workings behind it.

    I love writing about Python and have more than 5 years of professional experience in Python development. I like sharing about various standard libraries in Python and other Python Modules.
    IF YOU LIKE IT, THEN SHARE IT
    Advertisement

    RELATED POSTS