SoFunction
Updated on 2025-04-22

One article will help you understand what __init__.py is in Python

Friends, today we will talk about a low-key but crucial document in Python-__init__.py

To be honest, when I first started learning Python, many people (including me back then) were confused: "What? What will happen if I delete it?"

Some people may have heard that it is a "sign of the package", some people think it is "useless and can be ignored", and some people think it is "just a pretend document". Today, let's figure it out thoroughly__init__.pyWhat exactly does it do and how it affects the structure and operation of a Python project.

Understand Python module first

Chatting__init__.pyBefore, we have to figure out what is in PythonModuleandBagThese two concepts.

module: Simply put, it is just one.pyFile, some functions, classes or variables are written in it.

For example, there is a namemath_tools.pyThe file contains a bunch of mathematical tool functions, and it is a module.

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

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

Then, we can use it like this in other Python files:

import math_tools

print(math_tools.add(3, 5))  # Output 8

This isBasic usage of modules, nothing is difficult, right?

What is a Python package?

If you write more and more modules and the amount of code is getting bigger and bigger, you have to find a way to organize them. At this time, in PythonPackageIt comes in handy.

Package:oneFolders, contains multiple modules (.pydocument).

existBefore Python 3.3, if you want a directory to be recognized as a Python package, you must create it inside__init__.pydocument.But starting with Python 3.3, even if not__init__.py, Python can also recognize it as a package (called a "namespace package").

However, most actual projectsStill recommend adding__init__.py, because it can:

✅ Make sure that this folder is a package to avoid errors in identifying certain tools (such as packaging tools).

✅ Allows execution of specific code when package initialization, such as automatic import of submodules.

✅ Make import behavior more controllable and avoid unexpected naming conflicts.

For example, we have onemath_utilsThe directory contains several math-related modules:

math_utils/     # This folder is a package
│── __init__.py
│──
│──

in,andThey are two modules,__init__.pyCan be usedCustom package import behavior

So what is __init__.py for?

Although__init__.pyNo longer creating packagesRequiredcondition, but it is still an important component in Python projects.

Its main functions aretwo

1. Clearly mark the directory as a Python package

if__init__.pyIf it exists, the Python parser will know:"This directory is a Python package, not a normal folder."

Even if Python 3.3+ is not mandatory__init__.py, but plus it can:

✅ Avoid the Python interpreter mistakenly considering it to be a normal directory in some cases.

✅ Compatible with old versions of Python, allowing the code to run more stably in different environments.

✅ Make certain tools (such aspytestmypy) Better identify project structure.

2. Make the package be imported like a module

if__init__.pyIf you don’t write anything in it, then its function is just a “sign”. But if we are__init__.pyAdd some code to it and it canCustom package import behavior

Example 1: Let the package expose the submodule directly

# math_utils/__init__.py
from .basic import add, subtract
from .advanced import power

In this way, we can directly import the entiremath_utils, without writing.basicor.advancedCome on:

import math_utils

print(math_utils.add(2, 3))  # Output 5print(math_utils.power(2, 3))  # Suppose there is a power function in advanced

It's equivalent to saying,__init__.pyletThe package becomes like a large moduleSimilarly, the external one does not need to know the module structure inside, just use it directly.

Example 2: Package Initialization Operation

__init__.pyYou can also perform some initialization operations when the package is imported, such as loading configuration, setting logs, etc.:

# math_utils/__init__.py
print("The math toolkit loaded successfully!")  # As long as the import package is imported, this line of code will be executed

__init__.py What else can I do

In the Python project of a large manufacturer,__init__.pyIt is also often used to do these things:

1. Dynamically import submodules

In large Python projects, manual maintenance is maintained as more and more modules are added__init__.pyIt will become particularly complex and prone to errors. At this time, dynamic import of submodules becomes a hot topic.
Suppose we don't knowmath_utilsWhat modules are there in__init__.pyDynamically scan and load on import:

# math_utils/__init__.py
import os
import importlib

# Get the path to the current packagepackage_path = (__file__)

# Iterate through all .py files in the current directory (excluding __init__.py itself)for module in (package_path):
    if (".py") and module != "__init__.py":
        module_name = module[:-3]  # Remove the .py suffix        importlib.import_module(f"{__name__}.{module_name}")  # Dynamic import module

Effect:That way, when you write somewhere elseimport mypackage,allmypackageInside.pyThe files will be loaded automatically, no need to manuallyimportNow!

If you don't add dynamic import, you need to write this:

import math_utils.basic
print(math_utils.(1,2))

#If you directly import math_utils, an error will be reported: module 'math_utils' has no attribute 'basic'

Added dynamic import and can be written like this:

import math_utils
print(math_utils.(1,2))

2. Modules that control external exposure

Sometimes, we don't want toallSubmodules are automatically imported, but only part of them is exposed for external use. You can use it at this time__all__ComeManual controlAllowed to befrom mypackage import *Accessed module.

# math_utils/__init__.py
import os
import importlib

package_path = (__file__)
__all__ = []

for module in (package_path):
    if (".py") and module != "__init__.py":
        module_name = module[:-3]
        __all__.append(module_name)  # Modules exposed only in __all__        importlib.import_module(f"{__name__}.{module_name}")

Effect

from math_utils import *

print(basic)  # Only modules in __all__ can be imported

3. Lazy Import

If some modules are larger and loading them will affect performance, you can useLazy loading(lazy import) technology, imported when needed, not inimport mypackageAll loads at once.

# math_utils/__init__.py
import importlib

def lazy_import(name):
    return importlib.import_module(f"{__name__}.{name}")

module1 = lazy_import("basic")

Effect

so,basicIt will only be imported when it is first used, improving performance!

4. Do version control

__init__.pyYou can also add a version number to the package so that external code can access:

# math_utils/__init__.py
__version__ = "1.0.0"

Then, you can use it elsewhere:

import math_utils

print(math_utils.__version__)  # Output "1.0.0"

5. Hide internal implementation

Some modules are "internal" and do not want to be accessed externally. What should I do? Can be__init__.pyManual control inExposed content

# math_utils/__init__.py
from .basic import add, subtract

__all__ = ["add", "subtract"]  Things in # will not be directly imported

In this way, external use can onlymath_utils.add(),butmath_utils.advancedNo direct access.

Ending

about__init__.py, let’s stop talking about it! I hope this article can help you understand its function thoroughly and use it more confidently when writing Python projects in the future.

This is the article about this article about how to understand what __init__.py is in Python. This is all about this article. For more related Python __init__.py content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!