Introduction to Creating Python Packages: Directory Structure and Import Control with __init__.py

As the scale of a program grows and the number of module files (.py) increases, you will likely want to organize them into a single directory (folder). In Python, a collection of multiple modules organized by directory is called a “Package.” Packaging allows you to separate namespaces by functionality and keep large applications organized.

This article explains the steps to create a custom package and the role of the __init__.py file in controlling package behavior.


目次

Basic Structure of a Package

To create a package in Python, you basically follow these two steps:

  1. Create a folder (the folder name becomes the package name).
  2. Place module files (.py) and a special file named __init__.py inside that folder.

Example Directory Structure

Here is a configuration for creating a package named math_tools that provides calculation functions.

project_root/
  │
  ├─ main.py            <-- Script to execute
  │
  └─ math_tools/        <-- This is the package
       │
       ├─ __init__.py   <-- Package initialization file
       ├─ basic.py      <-- Module 1
       └─ geometry.py   <-- Module 2

Note on __init__.py: In Python 3.3 and later, a directory is recognized as a package even without __init__.py (Namespace Package). However, it is still common practice to create it to explicitly treat it as a regular package and to perform initialization processing. The content can be empty.


1. Creating Modules

First, create the modules that will be the contents of the package.

math_tools/basic.py

def add(a, b):
    """Simple addition"""
    return a + b

def subtract(a, b):
    """Simple subtraction"""
    return a - b

math_tools/geometry.py

class Rectangle:
    """Rectangle Class"""
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

2. Using the Package (Standard Import)

To use the created package, import it from main.py as follows. Use a dot (.) to traverse the hierarchy like package_name.module_name.

main.py

# Method 1: Specify modules to import
from math_tools import basic, geometry

# Usage
result = basic.add(10, 5)
rect = geometry.Rectangle(10, 20)

print(f"Addition: {result}")
print(f"Area: {rect.area()}")

Output

Addition: 15
Area: 200

3. Simplifying Imports with __init__.py

In the example above, you had to be aware of the internal module names basic and geometry when using them. By editing __init__.py, you can control “what features to expose” to the outside of the package and simplify imports.

math_tools/__init__.py

# Import specific functions or classes from modules within the package
# directly under the package
from .basic import add
from .geometry import Rectangle

# 'subtract' is not exposed (by design)

By writing this in __init__.py, the user can skip the module name and import functions or classes directly from the package.

main.py (Improved Version)

# Can read directly from the package
import math_tools

# Or: from math_tools import add, Rectangle

# Accessible as math_tools.add()
# (Instead of math_tools.basic.add)
result = math_tools.add(5, 8)

rect = math_tools.Rectangle(4, 5)

print(f"Addition (Short): {result}")
print(f"Area (Short): {rect.area()}")

Output:

Addition (Short): 13
Area (Short): 20

__init__.py acts as a “reception desk,” hiding (encapsulating) the existence of internal basic.py and geometry.py from the user, allowing you to design a library that is easier to use.


Summary

  • You can create a “Package” by organizing multiple modules into a directory.
  • It is common to place __init__.py in the directory.
  • Use it via from package import module.
  • By writing from .module import feature in __init__.py, you can expose features directly under the package and shorten the import statement for the user.
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次