__init__.py в Python: зачем он нужен и как с ним работатьФайл
__init__.py играет ключевую роль в функционировании модулей и пакетов. В этой посте разберём, зачем нужен этот файл, как его использовать, и какие трюки можно с ним провернуть.__init__.py используется для обозначения директории как пакета Python. Пакет — это просто каталог, содержащий код, который можно импортировать. До Python 3.3 файл __init__.py был обязателен для того, чтобы Python распознавал директорию как пакет. Начиная с Python 3.3, это уже не строго обязательно благодаря PEP 420, который ввёл поддержку 'implicit namespace packages'.Тем не менее,
__init__.py всё ещё активно используется, потому что он позволяет:— Настроить импорты, переменные окружения и т.д.;
— Реализовать алиасы и проксировать импорты;
— Управлять логикой и поведением при импорте.
Пример: простой пакет с
__init__.py
my_package/
├── __init__.py
├── module1.py
└── module2.py
В
__init__.py можно явно указать, какие модули экспортируются:
from .module1 import func1
from .module2 import func2
__all__ = ['func1', 'func2']
Теперь из внешнего кода можно написать:
from my_package import func1, func2
И это сработает — благодаря тому, что
__init__.py делает интерфейс «плоским».Что можно писать в
__init__.pyВсё, что угодно — это обычный Python-скрипт. Вот что часто в нём делают:
1. Инициализация логики:
import logging
logging.getLogger(__name__).addHandler(logging.NullHandler())
2. Упрощение структуры:
# Вместо длинного:
from my_package.module1.submodule import ClassA
# можно:
from my_package import ClassA
И в
__init__.py:
from .module1.submodule import ClassA
3. Версионирование:
__version__ = "1.0.0"
4. Работа с абсолютными и относительными импортами:
Python различает абсолютные и относительные импорты. Благодаря
__init__.py, относительные импорты типа from . import module1 работают корректно.Когда
__init__.py не нуженPEP 420 ввёл концепцию namespace packages — это директории без
__init__.py, которые Python всё равно распознаёт как пакеты. Это удобно, когда вы хотите:— Распределить один пакет между несколькими каталогами (например, для плагинной архитектуры);
— Избежать необходимости в поддержке пустых
__init__.py.Пример:
project/
├── pkg/
│ └── subpkg1/
│ └── a.py
└── other/
└── pkg/
└── subpkg2/
└── b.py
Если в
pkg/ нет __init__.py, Python объединит содержимое в один namespace package. Когда
__init__.py обязателен— При тестировании и использовании
pytest (некоторые тест-раннеры не обнаруживают модули без `__init__.py`);— При работе с устаревшими инструментами;
— При построении плоского интерфейса пакета;
— Для поддержки специфичных путей и логики импорта.
#основы