← Назад к вопросам

Чем отличается пакет от модуля в Python?

1.0 Junior🔥 231 комментариев
#Python

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пакет vs Модуль в Python: ключевые различия

В Python это два часто путаемых понятия, которые важны для организации кода в Data Engineering проектах.

Что такое модуль

Модуль — это один файл с расширением .py, содержащий Python код.

my_project/
├── utils.py          # ← это модуль
├── data_loader.py    # ← это модуль
└── main.py           # ← это модуль

Пример модуля:

# utils.py — это модуль
def calculate_mean(data):
    """Вычисляет среднее значение"""
    return sum(data) / len(data)

def calculate_std(data):
    """Вычисляет стандартное отклонение"""
    mean = calculate_mean(data)
    variance = sum((x - mean) ** 2 for x in data) / len(data)
    return variance ** 0.5

CONSTANT = 42

Использование модуля:

# main.py
import utils  # импортируем модуль

data = [1, 2, 3, 4, 5]
print(utils.calculate_mean(data))   # используем функцию из модуля
print(utils.calculate_std(data))
print(utils.CONSTANT)               # используем константу

Что такое пакет

Пакет — это директория, содержащая модули и специальный файл __init__.py.

my_project/
├── utils/                 # ← это пакет
│   ├── __init__.py       # ← обязательно!
│   ├── statistics.py     # ← модуль внутри пакета
│   ├── processing.py     # ← модуль внутри пакета
│   └── data.py           # ← модуль внутри пакета
├── pipeline/             # ← это тоже пакет
│   ├── __init__.py
│   ├── extract.py
│   ├── transform.py
│   └── load.py
└── main.py

Файл __init__.py — что там?

# utils/__init__.py
# Может быть пустым

# Или содержать инициализацию пакета
from .statistics import calculate_mean, calculate_std
from .data import load_data
from .processing import preprocess

# Экспортируем основные функции
__all__ = ['calculate_mean', 'calculate_std', 'load_data', 'preprocess']

print("Пакет utils инициализирован")

Ключевые различия

АспектМодульПакет
Что этоФайл .pyДиректория с __init__.py
СодержитКод, функции, классыДругие модули и пакеты
__init__.pyНЕ нуженНУЖЕН (обязательно!)
Импортimport moduleimport package.module или from package import module
СтруктураОдин файлИерархия файлов
Примерutils.pyutils/__init__.py + utils/stats.py + utils/data.py

Примеры импорта

Импорт из модуля:

# Вариант 1: импортируем весь модуль
import utils
utils.calculate_mean([1, 2, 3])

# Вариант 2: импортируем функцию
from utils import calculate_mean
calculate_mean([1, 2, 3])

# Вариант 3: импортируем с alias
from utils import calculate_mean as calc_avg
calc_avg([1, 2, 3])

Импорт из пакета:

# Вариант 1: из конкретного модуля в пакете
from utils.statistics import calculate_mean
calculate_mean([1, 2, 3])

# Вариант 2: напрямую из пакета (если __init__.py экспортирует)
from utils import calculate_mean  # работает благодаря __init__.py
calculate_mean([1, 2, 3])

# Вариант 3: импортируем весь модуль из пакета
from utils import statistics
statistics.calculate_mean([1, 2, 3])

# Вариант 4: импортируем несколько функций
from utils import calculate_mean, load_data, preprocess

Практический пример: структура Data Engineering проекта

Хорошая структура:

data_pipeline/
├── config/                  # Пакет для конфигурации
│   ├── __init__.py
│   ├── settings.py         # Модуль
│   └── constants.py        # Модуль
│
├── data_sources/            # Пакет для источников данных
│   ├── __init__.py
│   ├── api.py              # Модуль для API
│   ├── database.py         # Модуль для БД
│   └── csv_loader.py       # Модуль для CSV
│
├── transformations/         # Пакет для трансформаций
│   ├── __init__.py
│   ├── cleaning.py         # Модуль
│   ├── aggregations.py     # Модуль
│   └── enrichment.py       # Модуль
│
├── utils/                   # Пакет для утилит
│   ├── __init__.py
│   ├── logging.py          # Модуль
│   ├── date_helpers.py     # Модуль
│   └── validators.py       # Модуль
│
├── pipeline.py              # Главный модуль (точка входа)
└── requirements.txt

Файл __init__.py для пакета:

# config/__init__.py
from .settings import DATABASE_URL, API_KEY, BATCH_SIZE
from .constants import TIMEOUT, MAX_RETRIES

__all__ = ['DATABASE_URL', 'API_KEY', 'BATCH_SIZE', 'TIMEOUT', 'MAX_RETRIES']

Использование в main коде:

# pipeline.py (точка входа)
from config import DATABASE_URL, BATCH_SIZE
from data_sources import load_from_api, load_from_database
from transformations import clean_data, aggregate_data
from utils import setup_logging, validate_data

def main():
    setup_logging()
    
    # Загружаем данные из разных источников
    api_data = load_from_api()          # из модуля api.py в пакете data_sources
    db_data = load_from_database()      # из модуля database.py в пакете data_sources
    
    # Валидируем
    validate_data(api_data)
    validate_data(db_data)
    
    # Трансформируем
    cleaned = clean_data(api_data)
    aggregated = aggregate_data(cleaned)
    
    # Сохраняем в БД
    with get_connection(DATABASE_URL) as conn:
        save_to_database(aggregated, conn, batch_size=BATCH_SIZE)

if __name__ == '__main__':
    main()

Пример реальной структуры: Spark ETL проект

spark_etl/
├── spark_etl/              # Пакет проекта
│   ├── __init__.py
│   │
│   ├── config/             # Пакет конфигурации
│   │   ├── __init__.py
│   │   ├── spark_config.py
│   │   └── env_config.py
│   │
│   ├── extractors/         # Пакет для Extract фазы
│   │   ├── __init__.py
│   │   ├── base.py         # Базовый класс
│   │   ├── csv_extractor.py
│   │   ├── api_extractor.py
│   │   └── database_extractor.py
│   │
│   ├── transformers/       # Пакет для Transform фазы
│   │   ├── __init__.py
│   │   ├── data_cleaner.py
│   │   ├── aggregator.py
│   │   └── validator.py
│   │
│   ├── loaders/            # Пакет для Load фазы
│   │   ├── __init__.py
│   │   ├── parquet_loader.py
│   │   ├── delta_loader.py
│   │   └── database_loader.py
│   │
│   ├── pipeline/           # Пакет для оркестрации
│   │   ├── __init__.py
│   │   └── etl_pipeline.py
│   │
│   ├── utils/              # Пакет для утилит
│   │   ├── __init__.py
│   │   ├── logging.py
│   │   ├── spark_utils.py
│   │   └── date_utils.py
│   │
│   └── main.py             # Модуль точки входа
│
├── tests/                  # Тесты
│   ├── __init__.py
│   ├── test_extractors.py
│   ├── test_transformers.py
│   └── test_loaders.py
│
├── requirements.txt
└── setup.py

Использование такой структуры:

# spark_etl/main.py
from spark_etl.config import get_spark_config
from spark_etl.extractors import CSVExtractor, APIExtractor
from spark_etl.transformers import DataCleaner, Aggregator
from spark_etl.loaders import DeltaLoader
from spark_etl.pipeline import ETLPipeline
from spark_etl.utils import setup_logging, get_spark_session

def main():
    setup_logging()
    spark = get_spark_session(get_spark_config())
    
    # Определяем компоненты
    extractors = [
        CSVExtractor(spark, 's3://raw/data.csv'),
        APIExtractor(spark, 'https://api.example.com')
    ]
    
    transformers = [
        DataCleaner(),
        Aggregator()
    ]
    
    loaders = [DeltaLoader('s3://warehouse/output')]
    
    # Запускаем pipeline
    pipeline = ETLPipeline(extractors, transformers, loaders)
    pipeline.execute()

if __name__ == '__main__':
    main()

__init__.py: обязательный файл

Python 3.3+ поддерживает namespace packages, но для явной структуры нужен __init__.py:

# utils/__init__.py (пустой файл)
# Достаточно для того, чтобы Python считал это пакетом

# utils/__init__.py (с инициализацией)
from .statistics import calculate_mean
from .processing import preprocess

__version__ = '1.0.0'
__all__ = ['calculate_mean', 'preprocess']

print(f"Loading utils package v{__version__}")

Вывод

Модуль vs Пакет:

  • Модуль = файл .py (например, utils.py)
  • Пакет = директория с __init__.py (например, utils/)

Когда использовать что:

  • Модули: для простых, небольших наборов функций (< 500 строк)
  • Пакеты: для организации кода в большие проекты с иерархией

Best Practice для Data Engineering:

  • Разбивай код на пакеты по функциональности (extractors, transformers, loaders)
  • Используй __init__.py для экспорта публичного API
  • Избегай импорта из приватных модулей (_internal.py)
  • Структурируй так, чтобы главный код был понятен с первого взгляда