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 просто хочет знать точно, где искать твои данные. Дай ему эту уверенность.