Усі файли створюй у тимчасовій теці (tempfile.mkdtemp()) або в окремій теці data/
поруч зі скриптом — і прибирай за собою. Дані вигадуй сам, з мережі нічого не тягни.
рівень 1Рівень 1 — База
Візьми свій набір даних — не кавʼярню з лекції. Наприклад: домашня бібліотека (назва, автор, рік, нотатка), список фільмів, витрати за тиждень. Потрібно 5-7 записів, і хоча б в одному полі мусить бути кома всередині значення (нотатка, опис, адреса).
- Запиши дані у CSV через
csv.DictWriterзnewline=""іencoding="utf-8". - Надрукуй файл як звичайний текст і подивись, де модуль сам поставив лапки.
- Прочитай файл двома способами: через
рядок.split(",")і черезcsv.DictReader. - Порівняй кількість полів в обох випадках.
Зроблено, якщо: у виводі видно рядок із лапками, надруковано кількість полів
для обох способів, і проходить assert про те, що поле з комою після DictReader
повернулось цілим одним значенням.
рівень 2Рівень 2 — Плюс
Ті самі дані, але з вкладеністю: додай кожному запису список (жанри книжки, теги витрати, актори фільму) — різної довжини в різних записів.
- Запиши це у JSON з
ensure_ascii=Falseтаindent=2. - Запиши те саме у CSV, склеївши список в одне поле через
|, і напиши функцію, яка розклеює його назад. - Порівняй розміри обох файлів через
.stat().st_size. - Спробуй записати той самий обʼєкт двічі: з
ensure_ascii=Falseі без нього. Порівняй розміри й переконайсяassert-ом, щоjson.loadsз обох рядків дає однаковий словник.
Зроблено, якщо: обидва файли створено, надруковано їхні розміри, assert про
однаковість даних проходить — і в комірці-markdown (або в коментарі) написано
2-3 речення про те, який формат ти обрав би для цих даних і чому саме форма
даних, а не розмір, вирішує справу.
рівень 3Рівень 3 — Виклик
Напиши модуль-валідатор перевір_csv(шлях, схема), який читає файл і повертає
список знайдених проблем. схема — словник «назва стовпця → тип», наприклад
{"назва": str, "ціна": int, "рік": int}.
Валідатор має знаходити щонайменше чотири види проблем і для кожної повертати номер рядка у файлі:
- рядок коротший за шапку (у полі опинився
None); - рядок довший за шапку (зайві поля поїхали під ключ
None); - значення не перетворюється на потрібний тип (
int("сорок")); - обовʼязкове поле порожнє (
""— це не те саме, щоNone).
Далі зроби зворотну задачу: напиши csv_у_json(шлях_csv, шлях_json, схема), яка
читає CSV, застосовує типи зі схеми й записує коректний JSON — з ensure_ascii=False.
Якщо валідатор знайшов проблеми, JSON не створюється, а функція повертає список проблем.
Зроблено, якщо: на навмисно зіпсованому файлі (усі чотири поломки одночасно)
валідатор повертає чотири записи з правильними номерами рядків; на чистому файлі
повертає порожній список і створює JSON, який успішно читається json.load,
а ціни в ньому — числа, а не рядки.
Підказки
- Порожнє поле — це
"", відсутнє — цеNone. Це різні випадки, і плутати їх не можна: перше означає «людина не заповнила», друге — «стовпця взагалі не було». - Не пиши
ifдля перевірки «чи це число»: спробуйint(значення)всерединіtryі зловиValueError. Так само зfloat— і памʼятай про кому замість крапки в українській локалі. - Номер рядка зручно брати з
enumerate(читач, start=2): двійка тому, що перший рядок файлу забрала шапка, і рядок даних №1 фізично лежить другим. - Якщо валідатор виходить довгим — розбий його на маленькі функції, кожна з яких перевіряє одну річ і повертає список претензій. Так їх легше тестувати окремо.