Skip to content

📦 Python Packages Guide

Beginner-friendly documentation about Python packages, imports, modules, and project organization.

This document explains: - what packages are - how imports work - __init__.py - package organization - absolute vs relative imports - common beginner mistakes - project structure examples


📚 Table of Contents


📖 What is a Package?

A package is a folder containing Python modules.

Packages help: - organize code - separate logic - structure large projects - improve readability


📦 What is a Module?

A module is simply:

a Python file

Example:

utils.py

This file itself is a module.


🧱 Basic Package Structure

project/
│
├── main.py
├── parser/
│   ├── __init__.py
│   ├── config_parser.py
│   └── validator.py
│
└── render/
    ├── __init__.py
    └── draw.py

📥 Importing Modules

Import Entire Module

import math

Usage:

math.sqrt(25)

Import Specific Function

from math import sqrt

Usage:

sqrt(25)

📌 init.py

__init__.py tells Python that a folder should behave like a package.

Without it, imports may fail in some project structures.


🌿 Absolute Imports

Absolute imports start from the project root.

Example

from parser.config_parser import parse_config

🔗 Relative Imports

Relative imports use dots (.).

Example

from .validator import validate_config

🛠️ Organizing Large Projects

Example organization:

project/
│
├── core/
├── parsing/
├── render/
├── utils/
├── tests/
└── assets/
└── main.py

And each folder would have a init.py file to make it a package.


📌 init.py Contents

In many Python projects, __init__.py is often left empty.

Example:

# __init__.py

This is completely normal and commonly used only to mark the folder as a package.


Why Leave It Empty?

An empty __init__.py: - keeps the package simple - avoids unnecessary imports - helps Python recognize the directory as a package


What Can Be Inside init.py?

Although often empty, it may also contain: - package imports - helper variables - package initialization code - exposed public functions/classes


Example

from .config_parser import parse_config
from .validator import validate_config

This allows imports like:

from parser import parse_config

instead of:

from parser.config_parser import parse_config

Why This is Useful

This can: - simplify imports - expose public APIs - improve package organization

Very common in: - libraries - frameworks - large Python projects


Good Practice

For beginner projects: - keeping __init__.py empty is completely fine

As projects grow larger: - it may be used to organize package exports and initialization logic


⚠️ Common Beginner Mistakes

❌ Missing init.py

Problem:

ModuleNotFoundError

❌ Circular Imports

Example:

# a.py imports b.py
# b.py imports a.py

❌ Running Files Directly

Bad:

python3 parser/config_parser.py

Better:

python3 main.py

📚 Final Notes

Understanding packages is extremely important for modern Python development.

Good package organization helps: - readability - maintainability - debugging - scalability - teamwork