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, factorial.py.
File: factorial.py
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_1 and SPEED_2 with the values 5 and 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.
File: test_factorial.py
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 (.) operator.
Output:
Factorial of 5 is 120Now 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 fNow, we can use SPEED_1 and 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
Output:
Factorial of 5 is 120
Value of SPEED_2 = 10Note: 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 SPEED_1 and fact() as done below.
from factorial import fact, SPEED_1In this case, we can directly write variable and method names to use them.
print(fact(5))
print(SPEED_1)And we get the following output
Output:
120
5We 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.pyIf 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.
File: test.py
from source.code.factorial import fact
print(fact(5))Output:
120But what if we have a deep or complex folder structure? In that case, it will be impractical to use absolute paths.
Here, __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.pyAdd the following code inside the __init__.py file.
File: __init__.py
from .code.factorial import factNow, in our test.py file, we only have to write
from source import fact
print(fact(5))Output:
120Until 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 sys.path.
The following code will print a list of values inside sys.path.
from sys import path
print(path)Output
[
'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 0The search order is,
PYTHONPATH, which is an environment variable that contains a list of directoriesA module in a python script is imported only once by the interpreter for efficiency.
Consider the following module, printer.py
number = 5
print(number)Now if we import this module in our script file as
>>> import printer
5The value of number is printed.
Now let’s modify the printer.py module by changing the value of number to 6. But if we import the module again, we don’t see any output.
>>> import printer
5
>>> import printerWhy 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.
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)
6Python 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))We get,
Output:
[
'__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.
python printer.pyAnd we get the output,
6You 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.
File: printer.py
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))As imported
>> import printer
>> printer.fact(5)
120As a script file
C:\Users\user\PycharmProjects\my_project> printer.py 5
120In this section, we learned
Help us improve this content by editing this page on GitHub