# -*- coding: utf-8 -*- import logging import yaml from typing import Optional, Dict # Для Python < 3.9 используйте Dict, для Python 3.9+ можно просто dict logger = logging.getLogger(__name__) class ConfigError(Exception): """Базовый класс для ошибок конфигурации.""" pass class ConfigNotFoundError(ConfigError): """Файл конфигурации не найден.""" pass class InvalidConfigFormatError(ConfigError): """Ошибка формата YAML в конфигурации.""" pass def load_config(path: str) -> Optional[Dict]: """ Загрузка конфигурации из YAML файла. Обрабатывает ошибки чтения файла и парсинга YAML. :param path: Путь к файлу конфигурации. :return: Словарь с конфигурацией или None в случае ошибки. """ logger.debug(f"Попытка загрузки конфигурации из файла: `{path}`") try: with open(path, "r", encoding="utf-8") as f: config_data = yaml.safe_load(f) # Проверим, что YAML действительно распарсился в словарь if not isinstance(config_data, dict): msg = f"Содержимое файла конфигурации `{path}` не является словарем. Тип: {type(config_data).__name__}." logger.error(msg) raise InvalidConfigFormatError(msg) logger.info(msg=f"Конфигурация успешно загружена из `{path}`") return config_data except FileNotFoundError: msg=f"Файл конфигурации не найден: `{path}`" logger.error(msg) raise ConfigNotFoundError(msg) from None # from None подавляет цепочку исключений except yaml.YAMLError as e: # YAMLError - базовый класс для ошибок PyYAML (ошибки сканера, парсера и т.п.) msg = f"Ошибка парсинга YAML в файле `{path}`: {e}" logger.error(msg) raise InvalidConfigFormatError(msg) from e except IOError as e: # IOError или OSError для других проблем с доступом к файлу (например, права доступа) msg = f"Ошибка ввода-вывода при чтении файла `{path}`: {e}" logger.error(msg) raise ConfigError(msg) from e # Общее исключение для других ошибок ввода-вывода except Exception as e: # Отлавливаем любые другие непредвиденные исключения logger.critical( msg=f"Непредвиденная ошибка при загрузке конфигурации из `{path}`: {e}", exc_info=True # Добавляет трассировку стека в лог для лучшей диагностики ) raise ConfigError(f"Непредвиденная ошибка: {e}") from e