Файлы и работа с файловой системой в Python: pathlib, with и UTF-8
💻 Информатика · 9 класс
Читаем, пишем и дозаписываем текстовые файлы с явной кодировкой UTF-8, собираем пути объектами pathlib, закрываем файлы через with и обрабатываем FileNotFoundError. Все примеры проверены во временной папке.

Модуль pathlib: пути как объекты
Модуль pathlib входит в Python с версии 3.4 и представляет путь объектом. Сборка сегментов оператором / и проверки exists(), is_file(), is_dir() читаются естественно:
from pathlib import Path
base = Path('данные')
report = base / 'отчёт' / 'итог.txt'
print(report.exists()) # False, пока файл не созданПуть существует независимо от файла: объект Path можно собрать для несуществующего файла, а exists() честно вернёт False. Проверено выполнением.
Три режима и кодировка
| Режим | Что делает |
|---|---|
| 'r' | чтение; режим по умолчанию |
| 'w' | запись с нуля: старое содержимое стирается |
| 'a' | дозапись: новые строки добавляются в конец |
Файл открывают в текстовом режиме и указывают кодировку явно. В Python 3.15 по умолчанию включён режим UTF-8; если его отключить, используется кодировка локали. В более ранних версиях выбор тоже зависит от режима UTF-8 и настроек системы. Явное encoding='utf-8' задаёт формат независимо от этих настроек. Так нужно читать файлы, которые действительно сохранены в UTF-8; для файла в другой кодировке указывают её. Конструкция with гарантирует, что файл будет закрыт после блока, даже если внутри возникло исключение; это короче и надёжнее ручного close().
Пример 1. Журнал наблюдений
from pathlib import Path
path = Path('журнал.txt')
def add_record(text):
with path.open('a', encoding='utf-8') as f:
f.write(text + '\n')
def read_records():
try:
f = path.open('r', encoding='utf-8')
except FileNotFoundError:
return []
with f:
return [line.rstrip('\n') for line in f]
add_record('Первая строка')
add_record('Вторая строка')
print(read_records()) # ['Первая строка', 'Вторая строка']Режим 'a' не стирает старые записи — проверено: после двух вызовов add_record в файле ровно две строки, а повторный запуск не затирает их, в отличие от 'w'. Файл перебирается построчно, однако готовый список записей всё равно целиком хранится в памяти. Отсутствующий файл обрабатывается прямо при открытии: предварительная exists() не гарантирует, что файл не исчезнет сразу после проверки. Метод rstrip('\n') убирает перевод строки и сохраняет значимые пробелы; strip() убрал бы ещё пробелы и табуляции по краям.
Пример 2. Ошибки и структурированные данные
Обращение к несуществующему файлу выбрасывает FileNotFoundError — его и ловят:
from pathlib import Path
try:
text = Path('нет-такого-файла.txt').read_text(encoding='utf-8')
except FileNotFoundError:
text = ''Перехват конкретного типа важен: пустой except перехватил бы и опечатки в собственном коде. То же исключение возникает при записи в несуществующую папку — её нужно создать заранее через mkdir(). Для сохранения списков и словарей удобен модуль json:
import json
from pathlib import Path
data = {'имя': 'Аня', 'оценки': [5, 4, 5]}
json_path = Path('оценки.json')
with json_path.open('w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False)
with json_path.open('r', encoding='utf-8') as f:
assert json.load(f) == dataФлаг ensure_ascii=False оставляет кириллицу в JSON-тексте читаемой вместо escape-последовательностей. Кодировку файла задаёт encoding='utf-8' при открытии, а не этот флаг. Roundtrip-проверка (записали — прочитали — сравнили) выполнена и совпала.
Создание папок и просмотр содержимого
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as tmp:
folder = Path(tmp) / 'данные' / 'отчёт'
folder.mkdir(parents=True, exist_ok=True)
report = folder / 'итог.txt'
report.write_text('Готово\n', encoding='utf-8')
print(folder.is_dir(), report.is_file()) # True True
print(sorted(p.name for p in folder.iterdir())) # ['итог.txt']
renamed = report.rename(folder / 'готово.txt')
renamed.unlink()
folder.rmdir()
parents=True создаёт недостающие родительские папки, exist_ok=True допускает уже существующую папку. iterdir() перебирает её непосредственное содержимое; sorted делает порядок имён предсказуемым. rename переименовывает файл, unlink удаляет файл, rmdir — пустую папку. В примере эти операции выполняются только внутри временной папки.
Тестирование — только во временной папке
Код, работающий с файлами, проверяют в изолированном месте. Все примеры урока прогнаны через tempfile.TemporaryDirectory: папка создаётся пустой, после выхода из with удаляется вместе с содержимым. Никогда не тестируйте программы на личных файлах или реальных документах.
Проверь себя
- Чем режим 'a' отличается от 'w'? Ответ: 'a' добавляет строки в конец, сохраняя старое содержимое, а 'w' стирает файл и пишет сначала.
- Что будет, если прочитать несуществующий файл через read_text()? Ответ: FileNotFoundError; его можно перехватить и обработать.
- Зачем указывать encoding='utf-8' явно? Ответ: это явно задаёт формат файла и не зависит от версии Python, режима UTF-8 и настроек локали; сам файл должен быть сохранён в UTF-8.
- Как подготовить папку перед записью файла в неё? Ответ: для пути к файлу report создайте его родительскую папку через report.parent.mkdir(parents=True, exist_ok=True). Метод mkdir вызывают у пути папки, а не у имени файла.
Кратко о главном
pathlib превращает пути в объекты: сборка через /, проверки exists() и is_file(). Режимы: 'r' читает, 'w' перезаписывает, 'a' дозаписывает. with закрывает файл автоматически, кодировку UTF-8 задавайте всегда явно. Отсутствующий файл вызывает FileNotFoundError, а отсутствие прав — PermissionError; а для структур данных — json. Эксперименты проводите только в TemporaryDirectory.