Import And Create Modules In Python: The Misty Universe

We all know that programming is a way to solve real-world problems. Real-world problems are complex and will take up millions of lines of code to be solved. But, that would make the code impossible to manage, use, and understand.

And instead of solving problems, it would produce new problems for us. Modules in python provide you with a way to solve this. It allows you to group functions, variables, classes, etc. in a single python file.

We will explore how to import an external module using the math module. And will make our own module to solve the problem of water in an imaginary world. We will call this world The Misty Universe.

Previous post’s challenge’s solution

Here’s the solution to the previous post’s challenge. You can read it and you’ll understand it with ease as we haven’t done anything much here. We have just learned how to store data in CSV:

# strings for representing rock paper and scissors.
rock = '''
    _______
---'   ____)
      (_____)
      (_____)
      (____)
---.__(___)
'''

paper = '''
    _______
---'   ____)____
          ______)
          _______)
         _______)
---.__________)
'''

scissors = '''
    _______
---'   ____)____
          ______)
       __________)
      (____)
---.__(___)
'''
#imports
# for clearing the console
import os
# for working with csv
import csv

#adding extra variables
# player1 scores
pw = 0
pl = 0
pt = 0
# player2 scores
p2w = 0
p2l = 0
p2t = 0
#reading and storing data from existing file
with open("result.csv","r") as csvObj:
    content= csv.DictReader(csvObj)
    data_list = []
    for d in content:
        data_list.append(d)

    # Updating scores according to the existing file data
    pw=int(data_list[0]["Player1"])
    p2w=int(data_list[0]["Player2"])
    p2l=int(data_list[1]["Player2"])
    pl=int(data_list[1]["Player1"])
    pt=int(data_list[2]["Player1"])
    p2t=int(data_list[2]["Player2"])


# all the three strings in a list
choices = [rock, paper, scissors]

# asking player1's choice from the three
player1_choice = int(input("What do you choose? Type 0 for Rock, 1 for Paper or 2 for Scissors.\n"))
# clearing the screen so that player2 cannot know player1's choice.
os.system("cls")
# asking player2's choice from the three
player2_choice = int(input("What do you choose? Type 0 for Rock, 1 for Paper or 2 for Scissors.\n"))
os.system("cls")

# COMPARING THE CHOICES OF BOTH THE PLAYERS
# AND CHANING SCORES ACCORDINGLY

# If both had same choices than it would be a tie.
if player1_choice==player2_choice:
    print(f"Player1 choice:\n{choices[player1_choice]}\nPlayer2 choice:\n{choices[player2_choice]}")
    pt+=1
    p2t+=1
    print("Tie")

# if player1 choose rock and player 2 choose paper. Player2 wins
elif player1_choice==0 and player2_choice==1:
    print(f"Player1 choice:\n{choices[player1_choice]}\nPlayer2 choice:\n{choices[player2_choice]}")
    p2w+=1
    pl+=1
    print("Player2 won")

# if player1 choose paper and player 2 choose rock. Player1 wins
elif player1_choice==1 and player2_choice==0:
    print(f"Player1 choice:\n{choices[player1_choice]}\nPlayer2 choice:\n{choices[player2_choice]}")
    pw+=1
    p2l+=1
    print("Player1 won")

# if player1 choose rock and player 2 choose rock. Player1 wins
elif player1_choice==0 and player2_choice==2:
    print(f"Player1 choice:\n{choices[player1_choice]}\nPlayer2 choice:\n{choices[player2_choice]}")
    pw+=1
    p2l+=1
    print("Player1 won")

# if player1 choose scissors and player 2 choose rock. Player2 wins
elif player1_choice==2 and player2_choice==0:
    print(f"Player1 choice:\n{choices[player1_choice]}\nPlayer2 choice:\n{choices[player2_choice]}")
    p2w+=1
    pl+=1
    print("Player2 won")

# if player1 choose paper and player 2 choose scissors. Player2 wins
elif player1_choice==1 and player2_choice==2:
    print(f"Player1 choice:\n{choices[player1_choice]}\nPlayer2 choice:\n{choices[player2_choice]}")
    p2w+=1
    pl+=1
    print("Player2 won")

# if player1 choose scissors and player 2 choose paper. Player1 wins
elif player1_choice==2 and player2_choice==1:
    print(f"Player1 choice:\n{choices[player1_choice]}\nPlayer2 choice:\n{choices[player2_choice]}")
    pw+=1
    p2l+=1
    print("Player1 won")

#Incase user gives invalid input
else:
    print("invalid choice")

#Storing updated data in the file
with open("result.csv", "w",newline = '') as csvObj:
    heads = ["ltw", "Player1", "Player2"]

    ltw = [
          {"ltw":"wins","Player1":pw, "Player2":p2w},
          {"ltw":"looses","Player1":pl,"Player2":p2l},
          {"ltw":"ties","Player1":pt,"Player2":p2t}
    ]
    
    typer = csv.DictWriter(csvObj, heads)
    typer.writeheader()
    typer.writerows(ltw)

I hope it was easy. Try and play with the solution.

If you have made something like this for the first time it will feel super fun.💃🏇🏂🏄‍♀️

And in any case, if you weren’t able to solve it.

Happens no worries.🤗
Just play around with the code.
And when you are in a good mood 😊again.
Solve it on your own.🤔
Trust me doing this will make your learning process super fast.💨

Now let’s see what is a module in python.

What are modules in python?

A file is a module if it has:

  • A .py extension;
  • statements/classes/objects/functions/constants/variables are defined in it;
  • does not execute anything when you run it.

We have already seen this much about modules and also have been using them since our first program. Remember🤔the antigravity module which opened a comic 🗯💭 in your browser when you imported it and ran the program.

If you are in VS Code or Pycharm you can press control and click on antigravity a file having this code will open:

import webbrowser
import hashlib

webbrowser.open("https://xkcd.com/353/")

def geohash(latitude, longitude, datedow):
    '''Compute geohash() using the Munroe algorithm.

    >>> geohash(37.421542, -122.085589, b'2005-05-26-10458.68')
    37.857713 -122.544543

    '''
    # https://xkcd.com/426/
    h = hashlib.md5(datedow, usedforsecurity=False).hexdigest()
    p, q = [('%f' % float.fromhex('0.' + x)) for x in (h[:16], h[16:32])]
    print('%d%s %d%s' % (latitude, p[1:], longitude, q[1:]))

This is the module file that runs behind the scene whenever you run import antigravity.

Now I am sure you got what’s a module.

What is the need for a module?

You must be thinking ok I got it what is a module. But why is there a need for a module in python?

divide a large code into manageable chunks

Let’s say there’s a big desert in The Misty Universe. It is bigger than the Amazonia in our world. You are supposed to find out a small chocolate🍫 palace🏰 in this desert.

There are no guides, no google maps, and no divisions of states and towns in the desert. When do you think you’ll find your way?

Most probably never. Similar would be the case if you are given a code file that contains millions📝 of lines of code and you want to find out a specific function from it.

But what if there were divisions of states, cities, and towns inside this desert. It would be easier😉 to figure out in which town/city the chocolate🍫 palace🏰 is located and you will reach there much faster.

Dividing your code into modules works the same it gives you a map to the large code file and makes your code manageable and easy to use and access. It’s like using the principle of divide and conquer⚔. It always works.

to make the code reuseable

Say you were lucky🤘 enough to find out the chocolate🍫 palace🏰 in the desert without its division into states/cities/towns.

But what if you need to go to that palace again after 5 years. Will you go to figure out the way to that palace again?

Most probably you’ll try to recreate that palace🍫🏰 near your house🏡 so that you don’t need to go there again and again. But won’t that be a waste of resources?

In code too, if once you found the function you wanted you might want to make a copy of that function in your current file. That’s not❌a pythonic way to work.

Better would be to create a module📁 and store that function and all the related functions there only. And then call the function from the module whenever required.

The difference between modules, packages, and libraries

You already know what’s a module.

A package is just a folder that has:-

  • a number of module files;
  • And a special __init__.py file that makes it a package.

A library is nothing more than a collection of packages.

These terms are usually used interchangeably but do have different meanings. All three can be

  • Built-in
  • External
  • User-Defined

Types of modules

As mentioned above modules in python can mainly be of three types:-

  1. Built-in: Comes with python installation like os, datetime, time, etc
  2. External: To be installed from the internet using pip(Pip Installs Packages) like pandas, NumPy
  3. User-Defined: You will make them for The Misty Universe in this post.

Ways to import a module into the program

Now it’s time to start using built-in and external modules in your programs. Both are used in the same ways described below. There are mainly 4 ways to use any module in your program:

We’ll use math🔢👩‍💻 which is a built-in module to understand these.

using the import statement

It is the easiest possible way to use any module in your program. Just type import keyword and the module name. Like this:-

import <moudule_name>
import math

Now to use any functionalities of this module just write module name followed by function/variable name and separated by “.“. Using functions this way is called dot notation.

import math
squareRoot = math.sqrt(144)
print(squareRoot)

Output:

12.0

The sqrt function of the math module finds out the square root of the number given as an argument.

from import to get specific functions

This way is used when we only want to use some functions from the module. It will make the code clear and won’t occupy much space.

Type keyword from followed by module name, followed by import keyword, followed by the objects you want to get in a comma-separated sequence.

from <module_name> import <objects_comma_separated>

Say you just want to find out the square root of 100 and want to know the result of 10 raised to power 2.

In this case, it’s better to get only sqrt and pow functions in your program as it would be useless to get all the functions.

from math import sqrt, pow

squareRoot = sqrt(100)
power = pow(10, 2)
print(squareRoot)
print(power)

Output:

10.0
100.0

from import * to get all

This method is used when you don’t want to use the module name again and again to use its functions.

Type the keyword from module_name import and lastly an asterisk.

from <module_name> import *

This will import everything from the module and you won’t need to write its name every time you use its functions.

Example:

from math import *
positive_float_num = fabs(-132)
print(positive_float_num)

Output:

132.0

fabs function turns an integer given inside it, to a positive float number.

Using this method is not recommended as it hampers the readability of the code. And can lead to errors and unexpected outputs as two modules can have functions with the same name.

Alias in import: give your module a pet name

This method saves you from writing the full name of the module. It neither hampers the readability of your code nor it in anyways can lead to errors.

Syntax:

import <module_name> as <any_pet_name>

Let’s import the math module with the pet name m.

import math as m
squareRoot = m.sqrt(144)
print(squareRoot)

Output:

12.0

Once we have defined an alias name, we should use only the alias. And should avoid using the original name. As it may result in an unexpected output or an error.

You can use an alias in all the above methods. You can also use an alias for the functions and variables that you import.

How python locates modules

Whenever you import a module python searches for it in the following sequence:

  • The current directory(The folder in which your python file is)
  • If it’s not there then, it searches in the PYTHONPATH variable. It is a variable that has a list of directories(folders)
  • If not even there then finally, it searches in the default path which is where python is installed on your system.

This is why you are always recommended not to use the module name as the name of any of the python files.

two helpful functions

These two functions are very useful for you while working with python let’s see how.

help()

It is used to know the purpose of a function and how it is used.

help function does not return anything.

There is a strong chance that you sometimes forget to use the built-in functions of python. Say you forgot how to use the fabs function of the math module.

There could be two possible ways to do it:

  • Google it. This is not always possible as you may not be connected to the internet.
  • use the help function.

Here’s how to use it.

help(function_name)
from math import fabs
help(fabs)

Output:

Help on built-in function fabs in module math:

fabs(x, /)
    Return the absolute value of the float x.

dir()

dir() when applied to a module, returns the names of all that is defined inside the module in the form of a list.

Let’s what’s inside the math module.

import math
inside_math = dir(math)
print(inside_math)

Output:

['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh',
 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos',
 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs',
 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf',
 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma',
 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi',
 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh',
 'tau', 'trunc', 'ulp']

You can also consider iterating through the list using for loop.

You must be waiting to know when will we make our own module to solve a problem of The Misty Universe. The wait is over now let’s make them.

Creating your own module

The Misty Universe is suffering from the problem of water management. Due to this, some areas suffer draughts and some areas floods and tsunamis.

To solve this the ruler👑 decided that all the children in the schools will be given a lecture once a week to think about the solutions to the problem and try and implement them.

This approach turned out to be successful and a large number of suggestions came to the ruler👑. The ruler loved one solution which was:

I suggest that we should install a machine in all the houses. This machine will collect water from everywhere in surroundings.

This collected water will be sent to a big storage house that we can create in our desert due to the availability of large space.

This storage house will have a software that will accept water from the areas only if the area’s water level is above a certain level.

Hope this will help our The Misty Universe.

The ruler called you to his palace. And asked you to help him and create a python module that has this function in it.

Ok so let’s get started.

  • First of all, make a new file water_management.py (you can choose any other name)
  • Then you need to define a function. Name it accept_decline (or anything else.)
def accept_decline():
  • This function should take area_name and water_level as arguments.
def accept_decline(area_name, water_level):
  • The function should check if the water level is above 95 or not.
  • If it is the function should return a string f"Accept water from {area_name}".
  • If it is not then the function should return this string f"Decline water from {area_name}".
def accept_decline(area_name, water_level):
    if water_level > 95:
        return f"Accept water from {area_name}"
    else:
        return f"Decline water from {area_name}"
  • Our function is almost ready just give it a docstring now.
def accept_decline(area_name, water_level):
    """Accepts or declines to take water from an area based on on water level.
       In both the cases returns an f-string"""
       
    if water_level > 95:
        return f"Accept water from {area_name}"
    else:
        return f"Decline water from {area_name}"

And, it is done your function along with your module is ready. This is a python module with one function in it.

Restrictions on module names

“Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability.” This is written in the PEP 8 Style Guide for Python.

The restrictions on naming modules are the same as naming a variable:

  • You Cannot Use Numbers At The Start Meaning A Module Name Cannot Be —> '1python'.
  • You Are Free To Use All The Alphabets From A-Z And A-Z.
  • Numbers Can Also Be Freely Used. But, Not In The Beginning. Like A Module Can Be —-> 'Python1' Or 'P1ython'
  • Special Characters Like @#$%^&*()- Or Any Other Are Also Not Allowed.
  • You Can Use An Underscore '_' Anywhere In The Module name.
  • There Must Be No Use Of White Spaces.
  • You Cannot Also Use Any Sort Of Reserved Words.

To read more about guides on import click here.

To read more about guides on modules click here.

__name__ variable

It is a special variable whose value is __main__ whenever we are in the same module. But, when the module is imported then its value is set to the module’s name.

For example, if you print __name__ in the water_management module then its value would be __main__.

But if you use water_management module in another file say test.py then, __name__ will have value water_management.

In water_management.py

def accept_decline(area_name, water_level):
    """Accepts or declines to take water from an area based on on water level.
       In both the cases returns an f-string"""
       
    if water_level > 95:
        return f"Accept water from {area_name}"
    else:
        return f"Decline water from {area_name}"
print(f"water_management.py: {__name__}")

Output:

water_management.py: __main__

In test.py

import water_management
print(f"test.py file: {__name__}")

Output:

water_management.py: water_management
test.py file: __main__

if __name__ == “__main__”: is used to execute some code only if the file was run directly, and not imported. For example:-

In water_management.py

def accept_decline(area_name, water_level):
    """Accepts or declines to take water from an area based on on water level.
       In both the cases returns an f-string"""
       
    if water_level > 95:
        return f"Accept water from {area_name}"
    else:
        return f"Decline water from {area_name}"
if __name__ == "__main__":
    print("This would be only printed in water_management.py")

Output:

This would be only printed in water_management.py

In test.py

import water_management
print(f"test.py file: {__name__}")

Output:

test.py file: __main__

__main__

__main__ is the name of the environment where top-level code is run. To read more about top-level code click here.

Conclusion

In this post, we got to learn what are modules. And that they are needed to find the chocolate🍫 palace🏰 in the desert of The Misty Universe.

Then we saw what’s the difference between library, package, and module. We also saw three types of modules.

Next, we saw 4 different ways to get them into our program according to our requirements. We also saw how python locates these them. And saw help() and dir() functions.

After that, we helped in solving the problem of water in The Misty Universe by creating our own water_management.py.

Finally, we saw __name__ and __main__.

If you want to solve a number of questions on this topic you should consider going through this pdf. Click here to visit/download. !!This is not my own I found this resource helpful that’s why I am linking to it!!

Challenge🧗‍♀️

Your challenge for this post is to make your own stopwatch. Yes, you heard(sorry read) it right your own stopwatch.

Hints:

  • time module (it’s a built-in module) (time.time())
  • while True loop (You’ll need to stop it using ctrl c)
  • try and except (you need to use the basic one we will discuss them in detail in the next post)

Go fast. I am waiting. Comment your answers below.

This was it for the post. Comment below suggestions if there and tell me whether you liked it or not. Do consider sharing this with your friends.

See you in the next post till then have a great time.😊