Модуль 8 · Исключения и файлы

Справочник по Python · модуль 8 · исключения и файлы

Глава 8.13

8.13

Режим x:
создание файла

Режим создаёт новый файл и отказывается работать, если такой уже есть. Это защита от того самого сценария главы 8.6, где "w" молча стирает существующие данные: вместо тихой потери — явное исключение.

Категория
Файлы
Уровень
Базовый
Связанные темы
Режимы открытия, исключения
Зачем это знать
Гарантированно не перезаписать существующий файл

§1Проблема режима w

Глава 8.6 показала: open(path, "w") стирает содержимое в момент открытия. Если программа создаёт файл отчёта, а такой файл уже есть, прежние данные исчезнут — без предупреждения и без возможности вернуть.

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

§2Как работает режим x

Режим "x" — от exclusive creation, «исключительное создание». Он создаёт файл и открывает его на запись.

main.pyфайла ещё не было
with open("newfile.txt", "x", encoding="utf-8") as file:
    file.write("создан")

print(open("newfile.txt", encoding="utf-8").read())
Выводработает как обычная запись
создан

Пока файла нет, режим ведёт себя точно как "w". Разница проявляется во втором запуске.

§3Файл уже существует

main.pyтот же код запускаем повторно
with open("newfile.txt", "x", encoding="utf-8") as file:
    file.write("второй раз")
Ошибкафайл не тронут
FileExistsError: [Errno 17] File exists: 'newfile.txt'

Существующее содержимое осталось нетронутым: исключение возникает при открытии, до всякой записи. Именно это и требовалось — потерять данные невозможно.

§4Обработка исключения

FileExistsError — потомок OSError из главы 8.3, и обрабатывается как любое другое исключение.

main.pyсообщаем вместо аварии
try:
    with open("newfile.txt", "x", encoding="utf-8") as file:
        file.write("данные")
except FileExistsError:
    print("Файл уже существует, перезапись отменена.")
Выводпрограмма продолжает работу
Файл уже существует, перезапись отменена.

Дальше решение принимает программа: предложить другое имя, добавить к имени номер или спросить пользователя.

§5Двоичный вариант

Как и остальные режимы, "x" сочетается с буквой b.

main.pyсоздание двоичного файла
with open("data.bin", "xb") as file:
    file.write(b"bin")

print(open("data.bin", "rb").read())
Выводправила двоичного режима те же
b'bin'

Есть и форма "x+" — создание с возможностью чтения, по аналогии с "w+" из главы 8.6.

§6Сравнение режимов

РежимФайла нетФайл естьСмысл
"w"создаётстирает содержимое«мне нужен файл с этим содержимым»
"a"создаётдописывает в конец«добавь к тому, что есть»
"x"создаётFileExistsError«файл должен быть новым»
"r"FileNotFoundErrorчитает«файл должен существовать»

Последние две строки зеркальны: "x" требует отсутствия файла, "r" — его наличия. Оба сообщают о несоответствии исключением, а не молча.

§7Чем лучше проверки exists()

Тот же результат кажется достижимым проверкой перед открытием.

Сравнениедве попытки не перезаписать файл
import os                          между проверкой и открытием
                                   файл может появиться —
if not os.path.exists(path):       и тогда он будет стёрт
    with open(path, "w") as f:
        ...

with open(path, "x") as f:         проверка и создание —
    ...                            одна неделимая операция

Разница не теоретическая: если файл создаёт другая программа или другой процесс той же программы, между проверкой и открытием проходит время, и в этот промежуток файл может появиться. Режим "x" выполняет проверку и создание одним действием на уровне операционной системы, поэтому такого промежутка не возникает.

§8Где применяется

ЗадачаПочему "x"
создать файл-метку о запускевторая копия программы получит ошибку и не запустится
сохранить результат под новым именемслучайно не затереть прошлый результат
первичная настройка проектане испортить существующий конфиг
выгрузка с датой в имениобнаружить повторный запуск за тот же день

Общий признак: файл создаётся один раз, и его повторное создание — признак ошибки в сценарии работы, о которой лучше узнать.

§9Частые ошибки

Что написаноЧто произойдётКак правильно
"x" там, где файл перезаписывается регулярновторой запуск упадётрежим "w"
"x" без обработки исключенияпрограмма остановится при повторном запускеtry / except FileExistsError
проверка os.path.exists() перед "w"между проверкой и записью файл может появитьсярежим "x"
ждать дозаписи от "x"к существующему файлу он не откроется вовсережим "a"
ловить FileNotFoundError вместо FileExistsErrorисключение не будет перехваченоони противоположны по смыслу

§10Проверьте себя

Что делает режим "x", если файл уже есть?

Вызывает FileExistsError при открытии, не изменяя существующий файл.

Чем "x" отличается от "w"?

Оба создают файл, если его нет. Но "w" стирает существующий, а "x" отказывается работать.

Почему "x" надёжнее проверки os.path.exists()?

Проверка и создание выполняются одной операцией, поэтому файл не может появиться в промежутке между ними.

От какого класса наследует FileExistsError?

От OSError — как и остальные ошибки работы с файлами из главы 8.3.

Можно ли использовать "x" для двоичных файлов?

Да, режим записывается как "xb". Есть и "x+" для создания с возможностью чтения.

§11Шпаргалка

Создать новыйopen(path, "x", encoding="utf-8")
Двоичныйopen(path, "xb")
С обработкойexcept FileExistsError:
Перезаписатьopen(path, "w")
Дописатьopen(path, "a")

Итог главы

Режим "x" создаёт файл только при его отсутствии, а иначе вызывает FileExistsError — существующие данные при этом не страдают. Он зеркален режиму "r", который требует, чтобы файл был. Главное его преимущество перед проверкой os.path.exists() в том, что проверка и создание выполняются одной неделимой операцией, и файл не может появиться в промежутке. Этим завершается разбор режимов открытия и всего модуля о файлах.

Глава 8.13 · Режим x · Справочник по Python Автор: Макаров Максим Николаевич