Errors
Great Expectations

Great Expectations: Great Expectations: base_directory must be an absolute path if root_directory is not provided

Ты вдохновился модной штукой под названием Great Expectations, решил наконец-то приструнить качество своих данных. Открываешь официальный гайд, копируешь код дл

Ты вдохновился модной штукой под названием Great Expectations, решил наконец-то приструнить качество своих данных. Открываешь официальный гайд, копируешь код для создания DataContext без yml-файла, запускаешь — и получаешь холодный и беспощадный ValueError: base_directory must be an absolute path if root_directory is not provided.

Знакомо. Документация вроде есть, но в самый нужный момент она оставляет тебя наедине с загадочной ошибкой.

Почему путь должен быть абсолютным

Ошибка возникает здесь, в конфигурации генератора пакетных аргументов:

"batch_kwargs_generators": {
    "subdir_reader": {
        "class_name": "SubdirReaderBatchKwargsGenerator",
        "base_directory": "./data",  # Вот эта строчка — источник боли

Great Expectations — серьезный инструмент. Он не любит неоднозначностей. Когда ты указываешь относительный путь вроде ./data или ../datasets, система не может однозначно определить, относительно чего этот путь строится. Относительно текущей рабочей директории Python-процесса? А она где? В ноутбуке, в контейнере, в cron-задаче?

Поэтому правило железное: если ты не задал явно root_directory в конфигурации источника данных, то base_directory обязан быть абсолютным. Это не прихоть, а требование для детерминированной работы.

Быстрое решение на месте

Самый прямой способ — превратить путь в абсолютный. Не гадай, просто сделай это явно.

import os
from great_expectations.data_context.types.base import DataContextConfig, DatasourceConfig, FilesystemStoreBackendDefaults
from great_expectations.data_context import BaseDataContext

data_context_config = DataContextConfig(
    datasources={
        "my_datasource": DatasourceConfig(
            class_name="PandasDatasource",
            batch_kwargs_generators={
                "subdir_reader": {
                    "class_name": "SubdirReaderBatchKwargsGenerator",
                    "base_directory": os.path.abspath("./data"),  # Ключевое изменение
                }
            },
        )
    },
    store_backend_defaults=FilesystemStoreBackendDefaults(
        root_directory=os.path.abspath("./great_expectations")
    ),
)

context = BaseDataContext(project_config=data_context_config)

Функция os.path.abspath() возьмет относительный путь и привяжет его к текущей директории выполнения, получится что-то вроде /home/user/project/data. Проблема решена.

Правильный способ для прода

Хардкодить абсолютные пути в коде — не лучшая практика. Особенно если проект будет запускаться в разных окружениях.

Используй переменные окружения или конфигурацию приложения, чтобы определять корневую директорию данных динамически.

import os
DATA_ROOT = os.getenv('DATA_ROOT', '/default/absolute/path/to/data')

# ... в конфиге ...
"base_directory": os.path.join(DATA_ROOT, "raw")

Либо, что еще лучше, задай root_directory для всего источника данных. Тогда base_directory в генераторе может оставаться относительным — но уже относительно этого корня.

datasources={
    "my_datasource": DatasourceConfig(
        class_name="PandasDatasource",
        batch_kwargs_generators={
            "subdir_reader": {
                "class_name": "SubdirReaderBatchKwargsGenerator",
                "base_directory": "raw/",  # Относительно root_directory
            }
        },
        data_asset_type={
            "class_name": "PandasDataset",
        },
        root_directory="/mnt/shared/data",  # Явный корень для всего источника
    )
},

Итог

Ошибка про абсолютный путь — это не баг, а защита от хаоса. Решается либо явным приведением пути к абсолютному виду через os.path.abspath(), либо явным указанием root_directory для источника данных.

Не полагайся на относительные пути в конфигурации, особенно в продакшене. Great Expectations просто хочет знать точно, где искать твои данные. Дай ему эту уверенность.