Модуль 5 · Урок 17 із 58
Файли й pathlib: безпечна межа I/O
Файл — зовнішня межа, де припущення програми зустрічаються з реальною файловою системою. До читання треба визначити allowed root, формат, encoding, граничний розмір і поведінку для missing/empty input; до запису — ownership, overwrite policy та спосіб не залишити частковий результат.
Безпечна практика модуля 5
Пакет містить тільки synthetic JSON/CSV, explicit UTF-8, schema validation, deterministic output, safe logging і локальні tests. Жодних персональних чи production-даних, secrets, мережевих викликів або зовнішніх залежностей.
Path — це дані, а не склеєний string
from pathlib import Path
workspace = Path("workspace")
source = workspace / "input" / "records.txt"
report = workspace / "output" / "report.txt"Path виражає filesystem operation: join через /, exists(), is_file(), parent, suffix. Не будувати шлях конкатенацією з "/": separators відрізняються між platforms, а user-controlled absolute path може неочікувано вийти за intended workspace.
Text і bytes — різні contracts
with source.open("r", encoding="utf-8") as handle:
text = handle.read()
with Path("image.bin").open("rb") as handle:
payload = handle.read(1024)Text mode повертає str і виконує decoding; binary mode повертає bytes і не приймає encoding. Явний UTF-8 робить поведінку відтворюваною між Windows і Linux. errors="ignore" не є «виправленням»: він мовчки втрачає symbols і руйнує evidence.
with закриває resource навіть при exception
Context manager гарантує виклик cleanup після виходу з block. Це важливо не лише для memory: незакритий file descriptor, незаписаний buffer або locked file створює environment-dependent failures.
with source.open(encoding="utf-8") as handle:
first_line = handle.readline()
assert handle.closedНе повертайте відкритий handle із helper, якщо caller не володіє його lifecycle. Простіше повернути parsed values або зробити function itself context manager у пізнішому module.
Whole-file read має size contract
read_text() і read() зручні для малих контрольованих fixtures. Для невідомих або великих inputs використовуйте iteration по lines чи chunked binary reads і встановіть maximum bytes/records. Перевірка suffix не доводить content type або безпечність payload.
def iter_nonempty_lines(path: Path):
with path.open(encoding="utf-8") as handle:
for number, raw in enumerate(handle, start=1):
value = raw.strip()
if value:
yield number, valueЗапис не повинен тихо знищувати попередній результат
Mode "w" truncates existing file. Перед overwrite визначте policy: fail if exists, explicit --force, versioned filename або atomic replace. Для важливого report спочатку пишуть sibling temporary file, flush/close, а потім замінюють target у межах same filesystem. Це не робить multi-file operation transaction.
TemporaryDirectory, не machine-specific path.Definition of Done
- Paths створені через
Pathі не залежать від current working directory без документації. - Text/binary mode й encoding задані явно.
- Resource lifecycle закрито через
with. - Size, empty, missing, permission і overwrite cases мають очікуваний result.
- Тести працюють лише з temporary synthetic files.
Методичні джерела
Урок, сценарії, пояснення й вправи створені SEOWORK. Посилання ведуть лише на офіційну документацію Python.
Закріпіть матеріал уроку
Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.