Глава 15 · Python и файлы

Ошибки файловой системы

Файловые операции обращаются к внешнему миру — и внешний мир не всегда отвечает так, как хочется.

Частые ошибки файловой системы

ИсключениеКогда возникает
FileNotFoundErrorпуть не существует, а операция ожидала существующий файл
FileExistsErrorрежим "x" (или похожая операция) — а файл уже есть
PermissionErrorнет прав на чтение/запись этого пути
IsADirectoryErrorпуть — папка, а операция ожидала файл
NotADirectoryErrorпуть — файл, а операция ожидала папку
UnicodeDecodeErrorбайты не удаётся декодировать выбранной кодировкой (15.16)
Общий предок — OSError
Большинство файловых исключений — это разновидности OSError. Знать всю иерархию классов исключений не обязательно — достаточно уверенно распознавать перечисленные выше по имени и понимать, когда каждое из них возникает.

Чек-лист: файл не найден

  1. Что сейчас является CWD? (Path.cwd(), раздел 15.7)
  2. Какой именно путь был построен в коде?
  3. Существует ли родительская папка этого пути?
  4. Нет ли опечатки в имени?
  5. Путь абсолютный или относительный — и относительно чего?
  6. Совпадает ли регистр букв в имени файла?
Регистр имени файла — не мелочь
Поведение по чувствительности к регистру различается между файловыми системами. Не считайте, что Data.txt и data.txt — обязательно один и тот же файл: пишите код так, чтобы имя совпадало точно.
Debug Lab 11: Открыли папку как файл
papka_kak_fajl.py
from pathlib import Path

Path("arhiv").mkdir(exist_ok=True)
with open("arhiv", "r", encoding="utf-8") as f:   # "arhiv" — это папка!
    print(f.read())
Traceback (most recent call last):
IsADirectoryError: [Errno 21] Is a directory: 'arhiv'
Что видно на экране

"arhiv" — папка, а не файл, и её нельзя открыть как файл для чтения текста. Перед открытием стоило проверить .is_file().

Исправленный код
proverka_pered_otkrytiem.py
from pathlib import Path

path = Path("arhiv")
if path.is_file():
    with path.open("r", encoding="utf-8") as f:
        print(f.read())
else:
    print(f"{path} — не обычный файл")

Обрабатываем именно ту ошибку, которую ожидаем

targeted_except.py
from pathlib import Path

path = Path("nastroyki.json")
try:
    text = path.read_text(encoding="utf-8")
except FileNotFoundError:
    print("Файл настроек не найден — используем значения по умолчанию")
    text = "{}"
Никогда except: pass
Пустой перехват всех исключений подряд молча прячет реальные проблемы программы. Ловите конкретное ожидаемое исключение — как FileNotFoundError выше — а не всё подряд.

Чуть глубже: EAFP и LBYL

Два стиля: проверить заранее (if path.exists():) или попробовать и обработать ошибку (try/except). В Python операции с файлами часто пишут вторым способом — именно потому, что состояние файловой системы может измениться между проверкой и самой операцией (раздел 15.19). Запоминать сами английские сокращения не обязательно — важна идея.

Практика: ошибки файловой системы
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки
Открыть практику →