Modules & Imports
As your programs grow, one long file becomes hard to manage. Python lets you split code into modules: separate .py files that you load with the import statement. Python itself ships with hundreds of ready-made modules, called the standard library, for maths, dates, files, JSON and much more.
In this lesson you will learn the different ways to import, how to write your own module, what if __name__ == "__main__": means, and how to group modules into packages.
Importing a module
A module is simply a Python file. When you write import math, Python finds the math module, runs it once and gives you a name, math, through which you reach everything inside it with a dot.
import math
import statistics
print(math.sqrt(144))
print(math.ceil(7.2))
print(math.pi)
marks = [72, 85, 91, 64, 85]
print(statistics.mean(marks))
print(statistics.mode(marks))12.0 8 3.141592653589793 79.4 85
The dot shows clearly where each name comes from: math.sqrt is the square root function from the math module. Put your imports at the top of the file, one module per line.
Other ways to import
There are four common import forms. Each one suits a different situation.
import statistics as stats # 1. a shorter alias
from math import floor, factorial # 2. pick specific names
from datetime import date as Date # 3. pick a name and rename it
print(stats.median([4, 9, 2, 7, 5]))
print(floor(9.99), factorial(5))
print(Date(2026, 1, 26).year)5 9 120 2026
| Form | You write | Use it when |
|---|---|---|
import math | math.sqrt(9) | Most of the time; the source is always clear |
import statistics as stats | stats.mean(x) | The module name is long or has a common short form |
from math import sqrt | sqrt(9) | You use a few names many times |
from math import * | sqrt(9) | Avoid: it dumps every name into your file and can hide your own variables |
Writing your own module
Any .py file you write is a module that other files can import. Imagine two files in the same folder. The first one, gst_utils.py, holds reusable functions:
# gst_utils.py
GST_RATE = 18
def add_gst(price):
return round(price * (100 + GST_RATE) / 100, 2)
def gst_amount(price):
return round(price * GST_RATE / 100, 2)The second file, main.py, imports and uses them:
# main.py
import gst_utils
print(gst_utils.add_gst(1000))
print(gst_utils.gst_amount(1299))
print(gst_utils.GST_RATE)1180.0 233.82 18
Run it with python main.py from that folder. Python looks for modules first in the folder of the script you run, then in the standard library and finally in installed packages. The browser editor has only one file, so this runnable version writes gst_utils.py first and then imports it:
from pathlib import Path
Path("gst_utils.py").write_text(
"GST_RATE = 18\n"
"def add_gst(price):\n"
" return round(price * (100 + GST_RATE) / 100, 2)\n",
encoding="utf-8",
)
from gst_utils import add_gst, GST_RATE
print(add_gst(1000), GST_RATE)1180.0 18
The __name__ variable and if __name__ == "__main__":
Every module has a built-in variable called __name__. When you run a file directly, Python sets its __name__ to the string "__main__". When the file is imported, __name__ is the module's own name, such as "gst_utils".
This lets one file work both as a program and as a module. Code inside the if block below runs when you start the file directly, but not when another file imports it:
def add_gst(price):
return round(price * 1.18, 2)
def main():
print("Quick GST check:")
for price in [100, 499, 1299]:
print(price, "->", add_gst(price))
print("__name__ is", __name__)
if __name__ == "__main__":
main()__name__ is __main__ Quick GST check: 100 -> 118.0 499 -> 588.82 1299 -> 1532.82
Without this check, importing the file would also run its demo code and print output you did not ask for. Putting the program's start-up code in a main() function and calling it from this block is a common and tidy habit.
Packages: folders of modules
A package is a folder that groups related modules. A regular package contains a file called __init__.py, which runs when the package is first imported and is often empty. You import modules from it with dots.
shop/
__init__.py
billing.py
stock.py
main.py# main.py
from shop.billing import make_bill
from shop import stock
make_bill(["pen", "notebook"])
stock.check("pen")Packages you install with pip, such as requests, are organised the same way. You will install packages in pip & Virtual Environments.
Common mistakes
- Naming your file after a module. If you save your script as
random.pyorjson.py, thenimport randomloads your file instead of the standard one, and you get strange errors such asAttributeError: module 'random' has no attribute 'randint'. Recent Python versions add a hint to that message suggesting you rename your file. Do it. - Using
from module import *. You cannot tell where names come from, and imported names can silently replace your own. - Running a module from the wrong folder.
ModuleNotFoundError: No module named 'gst_utils'usually means you are not in the folder that contains the file. - Expecting a second import to rerun the file. Python runs a module only once per program and reuses it for later imports.
Key points
- A module is a
.pyfile;import nameloads it once and you reach its contents withname.something. import x as ycreates an alias, andfrom x import a, bbrings in chosen names; avoidimport *.- Your own files are modules too; Python searches the script's folder first.
__name__is"__main__"only when a file is run directly, soif __name__ == "__main__":holds start-up code.- A package is a folder of modules, usually with an
__init__.pyfile, imported with dotted names. - Python 3.15 adds
lazy importat module level to delay loading until first use.
Exercise
Create a module called cricket_stats.py with two functions: strike_rate(runs, balls), which returns runs per 100 balls rounded to 2 decimal places, and average(runs, outs), which returns runs per dismissal rounded to 2 places. Add an if __name__ == "__main__": block that prints a quick test. Then write main.py that imports the module and prints the strike rate for 87 runs off 54 balls and the average for 1,432 runs with 31 outs.
Show solution
# cricket_stats.py
def strike_rate(runs, balls):
return round(runs / balls * 100, 2)
def average(runs, outs):
return round(runs / outs, 2)
if __name__ == "__main__":
print("Test:", strike_rate(50, 25), average(300, 6))# main.py
import cricket_stats
print(cricket_stats.strike_rate(87, 54))
print(cricket_stats.average(1432, 31))161.11 46.19
Running python main.py prints only the two results. The test line in cricket_stats.py runs only when you start that file directly, because then its __name__ is "__main__".
Quick Quiz
1. What is a Python module?
Any Python file is a module that other files can import.
2. When does the code under if __name__ == "__main__": run?
When a file is run directly its __name__ is "__main__"; when imported, it is the module's name.
3. You saved your script as random.py, and import random now fails strangely. Why?
Python searches the script's folder first, so your file hides the standard module.
4. Where can you use lazy import json in Python 3.15?
PEP 810 lazy imports are allowed at module level only.
Learn Python with a mentor
Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
