Skip to content

Importing Guide

Fitri edited this page Sep 6, 2021 · 2 revisions

References and Resouces

https://stackoverflow.com/questions/32152373/python-why-can-i-import-modules-without-init-py-at-all

https://www.pythonforthelab.com/blog/complete-guide-to-imports-in-python-absolute-relative-and-more/

Importing Module from Standard Library

Module from standard library can be imported directly using import statement. The reason behind this is because all the path to the module for the standard lib was included in the env PYTHONPATH. We can append new path to **PYTHONPATH ** and python can directly use the module inside of the path using the import keyword directly.

Example importing module random from python standard lib:

The module can be imported as whole:

import random

#example use
random.choices(['a','b','c'], k=12)
Assigned to variable to local scope:
import random as ran

#example use
ran.choices([a,b,c], k=12)

Importing only one class/function:

from random import choices

#example use
choices([a,b,c], k=12)

Importing every method and class inside module:

from module import *

#example use
choices([a,b,c], k=12)

Module Searching Ordering

When we use import statement, python will prioritize finding the module within standard lib first, if the name not available inside of standard lib then python file find the file within local scope.

It's always the best we didn't name any of the local python module (python file) same as the builtin module to avoid conflict.

Example same naming local python file threading.py will have conflict with builtin module threading.

If the module bear the same name as the local module we want to call the local instead of the python standard lib module, we can initialized our folder as packages by including file init.py in the folder.

Finding order:

• Standard library
• Current directory
• External module (PYTHONPATH)

Checking which path will be imported:

import sys

for path in sys.path:
   print(path)

Importing Module from Source Environment

Module from environment can be imported directly as well after we source the environment. Sourcing the environment will replace the central python installation module with the new environment module path.

Importing from Same Directory

Asssuming two python file located within same dir structure on the same level we can import the module directly without any issues.

pythonmodule/
├── onemodule.py
├── __pycache__
│   └── onemodule.cpython-37.pyc
└── twomodule.py

1 directory, 3 files

As the tree structure above the onemodule.py and twomodule.py located in the same dir, so additional setup needed we can directly import the onemodule into twomodule directly, drop the .py when importing the module.

File twomodule.py:

import onemodule

onemodule.function()

File onemodule.py:

def function():
    print('Hi')

Same as the the importing from the central python path, module inside same dir can use statement like 'from' and 'as'

Importing from The Lower Directory

Starting from the python version 3.3 the file** __init__.py** no longer needed to find the module, but it's still needed to declare python folder as packages. So import still can work without the __init__.py

/home/fitri/pythonmodule
├── lower
│   ├── __pycache__
│   │   └── thirdmodule.cpython-37.pyc
│   └── thirdmodule.py
├── onemodule.py
├── __pycache__
│   └── onemodule.cpython-37.pyc
└── twomodule.py

3 directories, 5 files

From the directory structure above, importing thirdmodule inside of the twomodule can be done by calling the module path then module name.

File twomodule.py:

import lower.thirdmodule

lower.thirdmodule.secondfunction()

Same as all the other examples, this module import also can be used with statement 'from' and 'as'.

import onemodule
from lower import thirdmodule

onemodule.function()
thirdmodule.secondfunction()
import onemodule
from lower import thirdmodule as three

onemodule.function()
three.secondfunction()

Adding Local Folder to Path Environment

We can add the any local folder to the PYTHONPATH environment file using the two method:

Using sys.path:

import os
import sys

sys.path.append(os.getcwd)

Modifying the os environment PYTHONPATH:

$ export PYTHONPATH=$PYTHONPATH':/home/user/'

Importing from Absolute Path

Assumming the directories structure as the following:

/home/fitri/pythonmodule
├── first
│   └── one.py
├── second
│   └── two.py
└── start.py

2 directories, 3 files

In the first case, we want to import the function inside of two.py into the one.py, if we tried to import directly as we did like the the above example we will get failing error.

From first/one.py:

def onefunction():
    print('THis is one function')

From second/two.py:

from first import one

one.onefunction()

When we run the two.py module:

$ python two.py

Traceback (most recent call last):
  File "second/two.py", line 1, in <module>
    from first import one
ModuleNotFoundError: No module named 'first'

The file will return an error, this reason for this is very simple, as dicuss above, python will look for the name first inside standard library first, then it it can't found it, will will look into the current dir and subdirectories.

As the the folder first is not located inside of folder second (but on the same level) thus, it can't found the folder, as it only looking within second dir and subdir under its.

To solve this, we need to specify where this module located and let python know where it can find the module.

As discuss above, there's two way to do this which is including the parents dir to the PYTHONPATH env (recommended) and append it to the env on runtime.

Append the base dir to the PYTHONPATH env:

$ export PYTHONPATH=$PYTHONPATH':/home/fitri/pythonmodule'

After we done append and rerun, python will have no problem looking for the folder since it can browser the subdir under the pythomodule dir.

Keypoint here, if we want to use absolute path, we need to use the env PYTHONPATH since python need to find within the dir specified inside of the env for the folder and module.

Importing from Relative Path

pythonmodule/
├── first
│   ├── one.py
│   └── __pycache__
│       └── one.cpython-37.pyc
├── second
│   ├── __pycache__
│   │   └── two.cpython-37.pyc
│   └── two.py
└── start.py

4 directories, 5 files

Using the same dir structure, if we attempt to use relative path such as '.' (current dir) and '..' (upper dir) without running the pythol file as packages, we will encounter error.

From two.py:

from ..first import one

one.onefunction()

From one.py:

def onefunction():
    print('This is one function')

Running the two.py directly as module will encounter this error:

$ python two.py

ValueError: attempted relative import beyond top-level package

The right way to run this module is telling python to treat this as one packages:

$ python -m pythonmodule.second.two

It's recommended to use the absolute path with PYTHONPATH env variable as it's much simple and doesn't require the module to be run as package in commandline with python -m.

It's recommend to add every level with __init__.py to treat the folder as packages, so if the folder containing multiple module and we want to import all the module, we can import the package instead of individual module.

.
├── first
│   ├── one.py
│   └── __pycache__
│       └── one.cpython-37.pyc
├── second
│   ├── __init__.py
│   ├── numberone.py
│   ├── numbertwo.py
│   ├── __pycache__
│   │   └── two.cpython-37.pyc
│   └── two.py
└── start.py

4 directories, 8 files

From the dir above, if we want to import folder second as package we can add the __init__.py to initialize this as package then we can import the package itself instead of per module.

import second

second.two.function()