Слайд 3: Обработка исключений при работе с файлами

Теория: Основные исключения при работе с файлами

1. Базовые исключения:

# FileNotFoundError - файл не найден
try:
    with open('builds/venti.json', 'r') as file:
        data = file.read()
except FileNotFoundError:
    print("Билд не найден, используем стандартный")
    data = default_build_data

# PermissionError - нет прав доступа
try:
    with open('system_configs/settings.ini', 'w') as file:
        file.write('new settings')
except PermissionError:
    print("Недостаточно прав для изменения настроек")

2. Обработка нескольких исключений:

def save_character_data(character, filename):
    try:
        with open(filename, 'w') as file:
            json.dump(character.__dict__, file)
    except FileNotFoundError:
        print(f"Путь {filename} не существует")
        create_directory(os.path.dirname(filename))
        return save_character_data(character, filename)
    except PermissionError:
        print("Нет прав доступа, сохраняем в temp")
        alt_filename = f"temp/{os.path.basename(filename)}"
        return save_character_data(character, alt_filename)
    except json.JSONEncodeError:
        print("Ошибка сериализации")
        return False
    except Exception as e:
        print(f"Неизвестная ошибка: {e}")
        return False
    else:
        print("Сохранение успешно завершено")
        return True
    finally:
        # Всегда выполняется
        log_save_attempt(filename)

3. Собственные исключения:

class ArtifactImportError(Exception):
    """Ошибка при импорте артефактов"""
    pass

class InvalidBuildFormat(Exception):
    """Неверный формат билда"""
    pass

def import_artifact_set(filename):
    try:
        with open(filename, 'r') as file:
            data = json.load(file)
            
        if 'set_name' not in data:
            raise InvalidBuildFormat("Не указано название сета")
            
        if not validate_artifacts(data['artifacts']):
            raise ArtifactImportError("Некорректные статы")
            
        return data
    except json.JSONDecodeError:
        raise InvalidBuildFormat("Некорректный JSON")
    except KeyError as e:
        raise InvalidBuildFormat(f"Отсутствует обязательное поле: {e}")

4. Контекстные менеджеры:

from contextlib import contextmanager

@contextmanager
def artifact_file(filename, mode='r'):
    """Контекстный менеджер для работы с файлами артефактов"""
    try:
        file = open(filename, mode)
        yield file
    except FileNotFoundError:
        print(f"Файл {filename} не найден")
        yield None
    finally:
        if 'file' in locals():
            file.close()

# Использование
with artifact_file('artifacts.json') as f:
    if f:
        data = json.load(f)
        process_artifacts(data)

Важно помнить:

  • Всегда указывайте конкретные исключения вместо общего Exception
  • Обрабатывайте исключения как можно ближе к месту их возникновения
  • Используйте finally для освобождения ресурсов
  • Создавайте собственные исключения для бизнес-логики
  • Логируйте исключения для отладки

Задача: Система безопасного сохранения

Создайте систему для надёжного сохранения и загрузки игровых данных:

Подсказка: Пример структуры системы сохранения:

class SaveManager:
    def __init__(self, base_dir: str):
        self.base_dir = Path(base_dir)
        self.backup_dir = self.base_dir / 'backups'
        
    def save(self, data: dict, filename: str):
        try:
            # Создание резервной копии
            self._create_backup(filename)
            
            # Попытка сохранения
            self._save_data(data, filename)
        except Exception as e:
            # Восстановление из резервной копии
            self._restore_from_backup(filename)
            raise SaveError(f"Ошибка сохранения: {e}")
            
    def _create_backup(self, filename):
        # Логика создания резервной копии
        pass