PythonModules

Modules

A module is simply a file containing Python code. Any file that ends in .py is a module, and its name is the filename without the .py extension. Modules let you organize related code — functions, classes, variables — into reusable files instead of cramming everything into one giant script.

Once code lives in a module, you can import it from another file. This is the foundation of how Python programs scale: instead of one huge file, you split logic across many small, focused modules and wire them together with imports.

Why use modules?
  • Reusability — write a function once, use it in many scripts.

  • Organization — group related functionality together (e.g. all math helpers in one file).

  • Namespacing — avoid naming collisions by keeping code inside its own module namespace.

  • Maintainability — smaller files are easier to read, test, and debug.

Ways to import

Python gives you a few different syntaxes for importing, depending on how much of the module's namespace you want to bring in.

Python
# 1. import the whole module — access members with a prefix
import math
print(math.sqrt(16))       # 4.0
print(math.pi)              # 3.141592653589793

# 2. import specific names directly into your namespace
from math import sqrt, pi
print(sqrt(16))              # 4.0
print(pi)                    # 3.141592653589793

# 3. import with an alias — common for long or conflicting names
import math as m
print(m.sqrt(25))            # 5.0

# 4. import everything (generally discouraged — pollutes your namespace)
from math import *
print(floor(3.7))            # 3
Note
Avoid from module import * in real projects — it makes it unclear where a name came from and can silently overwrite names you already have.
A quick hypothetical example

Imagine a file named shapes.py that defines a couple of helper functions:

Python
# shapes.py
def area_circle(radius):
    return 3.14159 * radius ** 2

def area_square(side):
    return side ** 2

Any other file in the same directory can now use it:

Python
# main.py
import shapes

print(shapes.area_circle(2))   # 12.56636
print(shapes.area_square(3))   # 9
The if __name__ == "__main__": guard

Every module has a built-in variable called __name__. When a file is run directly (e.g. python greetings.py), Python sets __name__ to the string "__main__". When that same file is imported by another module, __name__ is set to the module's own name instead.

This lets a single file work both as a standalone script and as an importable module — the guard only runs the "script" behavior when the file is executed directly, not when it's imported.

File: greetings.py

Python
# greetings.py
def greet(name):
    return f"Hello, {name}!"

def main():
    # This is the "script" behavior — only for direct execution
    name = input("What is your name? ")
    print(greet(name))

if __name__ == "__main__":
    main()
File: app.py

Python
# app.py
import greetings

# We only want the greet() function here — main() never runs,
# because __name__ is "greetings", not "__main__", during this import.
message = greetings.greet("Ada")
print(message)
Hello, Ada!
Tip
This pattern is extremely common in real-world Python code. It means a module can be both a reusable library and a runnable script, depending on how it's invoked.
Creating and importing your own module

Let's build a small calculator module with a few functions, then use it from a separate entry-point file.

File: calculator.py

Python
# calculator.py
def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

def multiply(a, b):
    return a * b

def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b
File: main.py

Python
# main.py
from calculator import add, subtract, multiply, divide

print(add(4, 5))         # 9
print(subtract(10, 3))   # 7
print(multiply(6, 7))    # 42
print(divide(20, 4))     # 5.0
9
7
42
5.0

As long as calculator.py and main.py live in the same directory, from calculator import ... works with no extra setup — Python finds calculator.py on its module search path automatically (more on this in The Import System).

Inspecting a module with dir()

The built-in dir() function lists all the names — functions, classes, variables — defined inside a module. This is a handy way to explore what a module offers without reading its source.

Python
import math

print(dir(math))
['__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']

Names surrounded by double underscores (like __name__ and __doc__) are special "dunder" attributes that Python itself uses. The rest — sqrt, pi, floor, and so on — are the module's public API.

Tip
Name your own modules carefully. A file named math.py or random.py in your project directory will shadow the standard library module of the same name, causing confusing import errors elsewhere in your code.