Usage of Import Keyword in Python

Basic concept

Namespace

See Namespace.

Search path

When importing a module in a python file, the python interpreter will search for the module according to the following priorites:

  • Built-in module: The modules in the same folder as our python file;
  • sys.path: sys.path includes some search paths. For examples, path of this python project. It is a list that we can modify. (When visiting it, we should import sys)
  • Environment variable path;
  • Std lib.

Module & package

In general, a module is a file ended with .py, that is, it is a python file. When importing a module, python interpreter will run this module, therefore, if we write some test statements in the imported module, it will be run.

Each module has a metadata called __name__. When a module is run as a usual module, the value of __name__ is __main__. When it is run as an imported module, the value of __name__ is the name of module. Therefore, if we want to test our module, we can put the test statement under if __name__ == '__main__'.

A package is a folder contains modules and file __init__.py. When importing a package, python interpreter will run __init__.py. Therefore, we should put our import statement in __init__.py.

We can create nested package, that is, ceate packages in a package.

1

Fig. 1. Nested package

Importing modules

When importing a module, the name of the module is its full path after one of the search path. For examples, you have a search path C:\Users\xx and a module to be imported C:\Users\xx\yy\module_1.py, then your code is:

1
import yy.module_1

Python will do the following things when it interprets a import statement:

  • Create a new and empty module object;
  • Load this object to sys.modules (sys.modules is a dictionary that stores all the modules that can be recogized in current file);
  • Find this module through search path and load, run this module.

When using import to import modules that under other folder, python only puts the first file to namespace, that is, if you:

1
import yy.module_1

only yy will be put into namespace. Therefore, if you want to visit functions in module_1, you must start from yy:

1
yy.module_1.func()

However, if using from ... import ..., python will put the function or class or module after import to namespace:

1
2
from yy.module_1 import func
func() # You can directly visit func()

If the module we import imports other modules, we must make sure that python can find these modules in the current file (by modifying sys.path).

Importing packages

Importing a package is almost the same as importing a module. However, since package can not be run, python will run __init__.py once we import something from the package. Therefore, we can put the statements about importing modules in __init__.py. Then, we can just import the package and all the modules will be imported. In contrast, if __init__.py is empty and we only import the package, we will get nothing. The follwing is the structure of a python project:

1
2
3
4
|-->pack1
|-->__init_.py
|-->mod1.py
module_test.py

If __init__.py is empty and we import pack1 in module_test.py:

1
2
3
import pack1

pack1.mod1.func()

Then we will get:

1
AttributeError: module 'pack1' has no attribute 'mod1'

Similarly, we must make sure that python can find these modules in the current file when we import the package since the search path of __init__.py will become the search path of the current file if the package is imported:

1
2
3
4
5
6
7
# Run __init__.py directly:
print(sys.path)
# We get: 'C:\\Users\\xxx\\PycharmProjects\\Foundation\\module_myself\\pack1'

# Run __init__.py when importing pack1 in module_test.py
print(sys.path)
# We get: 'C:\\Users\\zcl\\PycharmProjects\\Foundation\\module_myself'

Some correct ways to import mod1.py:

  1. Import module:

    1
    2
    3
    4
    5
    6
    # __init__.py
    from . import mod1 # . is still the PWD of __init__.py, that is xxx\pack1

    # module_test.py
    import pack1
    pack1.mod1.func() # namespace just has pack1
  2. Import fucntion:

    1
    2
    3
    4
    5
    6
    # __init__.py
    from .mod1 import func

    # module_test.py
    import pack1
    pack1.func()

    Since __init__.py is also a python file, its behaviours are the same as common file. Therefore, it will add mod1 or func to its namespace.

  3. Import:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # __init__.py
    import mod1

    # module_test.py
    import sys
    sys.path.append('xxxxxxxx\\pack1') # Add path before importing

    import pack1
    pakc1.mod1.func()

The most important thing we must remember is that when importing a module or package that has imported other modules or packages, we must make sure that these modules or packages can be found in the current file.

Reference