Packages

Back

Loading concept...

📦 Python Packages: Building Your Code City

Imagine you’re building a city made entirely of LEGO blocks. Each block is useful, but a city needs neighborhoods, streets, and districts to keep things organized. That’s exactly what Python packages do for your code!


🏘️ The Big Picture: What Are Packages?

Think of it this way:

Real World Python
A single LEGO block A function
A small toy house A module (.py file)
A whole neighborhood A package (folder of modules)

A package is simply a folder that contains Python files (modules) grouped together. It’s how you organize your code when your project grows bigger!


🏗️ Creating Packages

It’s as easy as making a new folder!

Let’s say you’re building a game. You might organize it like this:

my_game/
    __init__.py
    player.py
    enemies.py
    weapons/
        __init__.py
        sword.py
        bow.py

The Recipe:

  1. Create a folder with your package name
  2. Add an __init__.py file inside it
  3. Add your Python modules (.py files)

That’s it! You just created a package! 🎉

Quick Example:

# File: my_game/player.py
def create_player(name):
    return {"name": name, "health": 100}

Now you can use it:

from my_game import player

hero = player.create_player("Luna")
print(hero)
# {'name': 'Luna', 'health': 100}

📜 The __init__.py File

What Is It?

The __init__.py file is like a welcome sign for your package. It tells Python: “Hey! This folder is a package, not just a random folder!”

The Magic Part

This file can be completely empty—and it still works! But you can also put code in it to make your package easier to use.

graph TD A["Folder: my_game"] --> B["__init__.py"] A --> C["player.py"] A --> D["enemies.py"] B --> E["Tells Python: I'm a package!"]

Empty vs. Filled

Empty __init__.py:

# Nothing here—just exists!

Smart __init__.py:

# my_game/__init__.py
from .player import create_player
from .enemies import spawn_enemy

# Now users can do this:
# from my_game import create_player

When you add imports to __init__.py, users get a shortcut. Instead of digging through files, they import directly from the package!


🧭 Absolute Imports

The Full Address

Absolute imports use the complete path from the top of your project. It’s like giving someone your full home address:

“123 Oak Street, Maple City, Sunshine Country”

# Always starts from the top-level package
from my_game.weapons.sword import swing
from my_game.player import create_player

When to Use Absolute Imports

✅ Your code is clear about where things come from ✅ Works anywhere in your project ✅ Recommended by Python style guides (PEP 8)

Example:

# File: my_game/battle.py

# Absolute import - full path
from my_game.weapons.sword import swing
from my_game.player import create_player

def start_battle():
    hero = create_player("Aria")
    swing()

🔄 Relative Imports

The Shortcut Directions

Relative imports use dots to say “look nearby!” It’s like saying:

“Go next door” instead of the full address.

Symbol Meaning
. Current package (same folder)
.. Parent package (one folder up)
... Grandparent (two folders up)

Example Time!

my_game/
    __init__.py
    player.py
    weapons/
        __init__.py
        sword.py
        bow.py

Inside my_game/weapons/sword.py:

# One dot = same folder (weapons)
from .bow import shoot_arrow

# Two dots = parent folder (my_game)
from ..player import create_player

The Golden Rule

⚠️ Relative imports only work inside packages!

You can’t use them in a script you run directly. They’re for files that are part of a package.

graph TD A["my_game"] --> B["weapons folder"] B --> C["sword.py"] B --> D["bow.py"] C -->|"from .bow"| D C -->|"from ..player"| E["player.py"] A --> E

📋 The __all__ Variable

The Guest List

Imagine you’re throwing a party and you make a list of who’s invited. The __all__ variable is exactly that—a guest list for your module!

It controls what gets imported when someone uses:

from my_module import *

How It Works

# File: my_game/player.py

__all__ = ['create_player', 'Player']

def create_player(name):
    return {"name": name}

class Player:
    pass

def _secret_function():
    # This WON'T be imported with *
    pass

def helper_function():
    # This also WON'T be imported
    # (not in __all__)
    pass

The Result

from my_game.player import *

# ✅ create_player is available
# ✅ Player is available
# ❌ _secret_function is NOT available
# ❌ helper_function is NOT available

Why Use __all__?

  1. Control what users see — Hide messy internal code
  2. Clear public API — Tell users “these are the important things”
  3. Cleaner imports — Prevent namespace pollution

Pro Tip

Even if you don’t use from x import * yourself, defining __all__ is good practice. It documents your module’s public interface!


🎯 Putting It All Together

Let’s build a mini package from scratch:

calculator/
    __init__.py
    basic.py
    advanced.py

calculator/basic.py:

__all__ = ['add', 'subtract']

def add(a, b):
    return a + b

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

def _internal_check(x):
    # Hidden helper
    return x > 0

calculator/advanced.py:

__all__ = ['power', 'sqrt']

def power(base, exp):
    return base ** exp

def sqrt(n):
    return n ** 0.5

calculator/init.py:

# Make common functions easy to access
from .basic import add, subtract
from .advanced import power, sqrt

__all__ = ['add', 'subtract',
           'power', 'sqrt']

Using your package:

# Method 1: Direct from package
from calculator import add, sqrt
print(add(5, 3))      # 8
print(sqrt(16))       # 4.0

# Method 2: Import module
from calculator.basic import subtract
print(subtract(10, 4))  # 6

# Method 3: Star import (uses __all__)
from calculator import *
print(power(2, 8))    # 256

🌟 Quick Summary

Concept What It Does Remember It As
Package Folder with __init__.py A neighborhood of code
__init__.py Makes folder a package The welcome sign
Absolute Import Full path from project root Full home address
Relative Import Dots for nearby modules “Next door” directions
__all__ Controls * imports The VIP guest list

🚀 You Did It!

You now understand how Python organizes code at scale! Packages might seem like extra work at first, but they’re what make large projects possible.

Start small—create a folder, add __init__.py, and you’re officially a package architect! 🏛️

“Great code is organized code. And organized code lives in packages.”

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.