Topic 09 / 15

Modules, Packages & Imports

~8 min read  //  Python Series  //  Coding India

Every File Is a Module

Any .py file can be imported. Given helpers.py:

# helpers.py
TAX_RATE = 0.18

def with_tax(amount):
    return round(amount * (1 + TAX_RATE), 2)

Use it from another file in the same directory:

# main.py
import helpers
print(helpers.with_tax(100))        # 118.0

# or import names directly
from helpers import with_tax, TAX_RATE
print(with_tax(100))

Avoid from helpers import * — it dumps unknown names into your namespace and makes code unreviewable.

Aliases

import numpy as np          # community-standard aliases
import pandas as pd
from datetime import datetime as dt

Packages — Directories of Modules

shop/
├── __init__.py        # marks the directory as a package
├── cart.py
├── payments.py
└── utils/
    ├── __init__.py
    └── currency.py
from shop.cart import Cart
from shop.utils.currency import to_inr

# inside the package, relative imports:
# shop/payments.py
from .cart import Cart
from .utils.currency import to_inr

The __main__ Guard

When a file is run, its __name__ is "__main__"; when it’s imported, __name__ is the module name. This idiom makes a file both importable and runnable:

# helpers.py
def with_tax(amount): ...

if __name__ == "__main__":
    # only runs with: python helpers.py
    # never runs on import
    print(with_tax(100))

Where Python Looks for Imports

Python searches, in order: the script’s directory, then PYTHONPATH, then installed packages (site-packages). The classic gotcha: never name your file after a library — a local random.py shadows the standard library’s random and breaks imports mysteriously.

The Standard Library Is Enormous

Before pip-installing anything, check what ships with Python: json, csv, datetime, pathlib, re, math, random, collections, itertools, functools, sqlite3, http, argparse, logging… “Batteries included” is real.