Cyberithub

Python: Packages, Sub-Packages and Modules with Best Examples

Advertisements

In this tutorial, we are going to look into Python Packages, sub-packages and modules with the help of best examples. In Python, packages are generally represented by directories in the File System while modules are represented by single file. Python basic tool to organize code is through modules. A module typically corresponds to a source file. We load modules into the program by using import keyword. When we import a module, it is represented by a type called module. We can interact with it like any other objects. More about Python Modules.

Python: Packages, Sub-Packages and Modules with Best Examples

Python: Packages, Sub-Packages and Modules with Best Examples

Also Read: Python: Introduction to Strings and Slices with Examples

Advertisements

A package in python is just a special type of module. The defining characteristic of a package is that it can contain other modules including other packages. So packages are a way to define hierarchy of modules in Python. To see an example, open your Python Interpreter and import urlib and urllib.requests and then check its type. You will see that both of them are module as shown below.

root@cyberithub:~# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> import urllib.request
>>> type(urllib)
<class 'module'>
>>> type(urllib.request)
<class 'module'>
>>>

If you look closely to each of the below objects, then you will notice an important difference.

Advertisements
>>> urllib.__path__
['/usr/lib/python3.8/urllib']
>>> urllib.request.__path__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'urllib.request' has no attribute '__path__'

 

1. How Does Python locate modules

Generally speaking, when you ask Python to import a module, python looks to your filesystem for corresponding source files and loads that code. But here the important questions is how python knows where to look ? Python finds that out from sys.path. It looks into first directory of sys.path. If no matches found in the first directory then it checks the next and so forth until a match is found or python runs out of entries in sys.path in which case a an import error is raised. Let's explore this further through Python Interpreter.

root@cyberithub:~# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']
>>>

Remember that sys.path is a general list so we can examine its contents by indexing and slicing. We can check the first entry of sys.path by using it like below. You can see that first entry is an empty string. This happens when you start the python interpreter with no arguments and it instructs python to search modules in current directory.

Advertisements
>>> sys.path[0]
''

To really get a feel for sys.path, let's create a directory called hello_world and a python source file called hello_test.py which will contain a function called hello(). This function will have the functionality to print a statement "Hello from CyberITHub !!" on the output as you can see below.

root@cyberithub:~# mkdir hello_world
root@cyberithub:~# cd hello_world/
root@cyberithub:~/hello_world# nano hello_test.py
def hello():
    print('Hello from CyberITHub !!')
root@cyberithub:~/hello_world# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append('hello_test')
>>> import hello_test
>>> hello_test.hello()
Hello from CyberITHub !!

 

2. Using PYTHONPATH

PYTHONPATH environment variable is a list of path that are added to sys.path when Python starts. The format of PYTHONPATH is same as your platform PATH variable. In Windows, it is a semi-colon separated list of directories while on Linux and MAC, it is colon separated list of directories. To see how PYTHONPATH works, let's add hello_world to it before starts python again. In Windows, you can use set command and in Linux or MAC if you are using bash shell then use export command.

Advertisements
root@cyberithub:~# export PYTHONPATH=hello_world
root@cyberithub:~# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> [p for p in sys.path if 'hello_world' in p]
['/root/hello_world']
>>> import hello_test
>>> hello_test.hello()
Hello from CyberITHub !!
>>>

 

3. Basic Package Structure

To create a package directory, first you need to create a package root directory somewhere in sys.path, then in that directory you create a file called __init__.py. This file which is called a package init file will make the package a module.

path_entry/
|
|__my_package/
   |
   |__ __init__.py

To understand this further, let's create a directory called example. Then to convert this directory into a package, create __init__.py file inside it. On Windows, you can use type command to create the file and on Linux or MAC Systems, you can use touch command as shown below.

root@cyberithub:~# mkdir example
root@cyberithub:~# touch example/__init__.py

Now if you start the Interpreter and try to import the directory then you can see it as a module.

root@cyberithub:~# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> type(example)
<class 'module'>
>>>

To see the role that __init__.py plays in the functioning of a package, check the __file__ attributes of the example package.

>>> example.__file__
'/root/example/__init__.py'

So we see that example is a module and the source file that is imported when example is imported is the package __init__.py file in the example directory. In other words, a package is just a directory containing a file name __init__.py.

To see that __init__.py is actually executed like any other module when you import example, let's add a small bit of code to it as shown below. Then start the interpreter again using python3 command and try to import example to see if the print statement shows on the output.

root@cyberithub:~# cd example/
root@cyberithub:~/example# nano __init__.py
print("Hi, This is from CyberITHub !!")
root@cyberithub:~/example# cd ..
root@cyberithub:~# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
Hi, This is from CyberITHub !!
>>>

 

4. Sub-packages

To really see how packages provides high level structure to Python code, let's see how we can add more layers of packages to the example hierarchy. We are going to add a sub-package called example_app which is going to contain code to display a print statement. So first let's create a new directory and package __init__.py file.

root@cyberithub:~# mkdir example/app
root@cyberithub:~# touch example/app/__init__.py
root@cyberithub:~# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example.app
>>>

Now, let's create another Python source file called testapp.py under example/app directory. Then start the Python Interpreter again and try to import example, example.app and example.app.testapp. You will see that all of them will be imported just fine.

root@cyberithub:~# touch example/app/testapp.py
root@cyberithub:~# python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> import example.app
>>> import example.app.testapp
>>>

Leave a Comment