In this article, we will be learning about modules in Python. Let us begin by defining the term module.
A module is a file that consists of constants, variables, functions, and classes. In python, modules have the extension
.py. It can be built-in or user-defined.
A module provides code reusability. We can import modules in a program (which we will be learning in the next section) and use its functions, classes, and variables so that we do not have to write them repeatedly hence reducing the length of the code.
For example, let’s start by creating a module,
SPEED_1 = 5 SPEED_2 = 10 def fact(number): if number in (0, 1): return 1 else: return number * fact(number - 1)
Here, we have defined constants
SPEED_2 with the values
10 and defined a function
fact() that takes a number as an input and returns its factorial.
In the next section, we will learn how to import modules and use their variables and functions in our code.
To import a complete module, Python provides us with a keyword
import. In the following example, we will import the
factorial.py module to calculate the factorial of a number.
import factorial num = 5 factorial_5 = factorial.fact(num) print("Factorial of %d is %d" %(num, factorial_5))
Here, we have accessed
fact() method of the
factorial module using the dot (
Factorial of 5 is 120
Now let’s say we want to use the
factorial module multiple times. To make our code compact, we can give alias name to the imported module by writing,
import factorial as f
Now, we can use
fact() method as
print("Factorial of %d is %d" %(f.SPEED_1, f.fact(f.SPEED_1))) print("Value of SPEED_2 = %d" %(f.SPEED_2))
Which also gives the same output
Factorial of 5 is 120 Value of SPEED_2 = 10
Note: If we give alias
f to the module, the module name
factorial will not be recognized anymore.
What if we only want to import the variable
SPEED_1 and the
fact() method? For this, we will only import
fact() as done below.
from factorial import fact, SPEED_1
In this case, we can directly write variable and method names to use them.
And we get the following output
We can also import all the functions, variables, and classes defined in the module using an asterisk (
from factorial import *
Note: Let’s say we create a variable, a function, or a class in our code with the same name as defined inside the module. It can lead to the definition duplicacy. Therefore, this method is not recommended.
There can be cases where we would like to import from subdirectories. To achieve that, we can use the absolute path of the module.
Consider the following folder structure
my_project # root folder(level 0) |-- test.py |-- util |-- printer.py |-- source # folder at level 1 |-- code # folder at level 2 |-- factorial.py
If we want to use the
fact() method of the
factorial module, we will have to go all the way up to folder level 2 and import
fact() as shown.
from source.code.factorial import fact print(fact(5))
But what if we have a deep or complex folder structure? In that case, it will be impractical to use absolute paths.
__init__.py comes into the picture.
We create an
__init__.py file inside a directory to be considered as a module. Also, inside the
__init__.py file, we can write the following code to reduce the path complexity for the above folder structure.
New folder structure
my_project # root folder(level 0) |-- test.py |-- util |-- printer.py |-- source # folder at level 1 |-- __init__.py |-- code # folder at level 2 |-- factorial.py
Add the following code inside the
from .code.factorial import fact
Now, in our test.py file, we only have to write
from source import fact print(fact(5))
Until now, we have learned about modules and how to import them. But how does the python interpreter find the modules we import?
First, the python interpreter looks for a built-in module. If the required module is not found, it looks into the directories mentioned in
The following code will print a list of values inside
from sys import path print(path)
[ 'C:\\Users\\user\\PycharmProjects\\my_project', 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python37-32\\python37.zip', 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python37-32\\DLLs', 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python37-32\\lib', 'C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python37-32','C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python37-32\\lib\\site-packages' ] Process finished with exit code 0
The search order is,
PYTHONPATH, which is an environment variable that contains a list of directories
A module in a python script is imported only once by the interpreter for efficiency.
Consider the following module,
number = 5 print(number)
Now if we import this module in our script file as
>>> import printer 5
The value of
number is printed.
Now let’s modify the
printer.py module by changing the value of
6. But if we import the module again, we don’t see any output.
>>> import printer 5 >>> import printer
Why is it so?
If we import a module and make changes to it, those changes will not be reflected in the current script. For this, we need to either restart the interpreter or reload the module by using the
reload() function is defined inside the
importlib module which we need to import.
>>> import printer 5 >>> import printer >>> from importlib import reload >>> reload(printer) 6
Python provides us with a function
dir() which can be used to find the names that are defined in a module. It returns a sorted list with the names of the functions, variables, and classes of the module. For example
import factorial print(dir(factorial))
[ '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fact', 'SPEED_1', 'SPEED_2' ]
Here, apart from the names defined inside the module
factorial, we get names with underscores. These are the default built-in python attributes provided to the module.
We already know that a module in Python is simply a Python script file with extension
.py. So, like any script file, the module can also be executed.
We can execute a module (
printer.py in our case) using
cmd on Windows or
terminal on Linux/Mac and run the following command.
And we get the output,
You may have noticed that we got the same output when we imported the
printer.py module in the
Reloading a module section. So, how do we differentiate between when we run the module as a script and when the file is imported as a module?
If the module is run as a script file, the python interpreter sets the special variable
__name__to the value
__main__. If this file is imported as a module,
__name__will be set to the name of the module.
So, we add the following code where we check if the value of
__name__ is equal to
__main__. If true, it will mean that the module is run as a script. Otherwise, it is imported as a module.
SPEED_1 = 5 SPEED_2 = 10 def fact(number): if number in (0,1): return 1 else: return number * fact(number - 1) if __name__ == '__main__': print(fact(5))
>> import printer >> printer.fact(5) 120
As a script file
C:\Users\user\PycharmProjects\my_project> printer.py 5 120
In this section, we learned