Бран · продюсер «Хроник Пограничья»
Финансисты прислали CSV с покупками. В названии предмета есть запятая, у одной оплаты нет суммы. Мне нужен файл с выручкой по платформам. Только не потеряй строки и не запиши пропуск как ноль.
В прошлом уроке ты передавал функции готовый список словарей. Теперь получишь такой список из файла. Пока без сторонних библиотек: так ты увидишь, где заканчивается текст и начинаются числа.
Сохрани шесть строк
В JupyterLab создай текстовый файл purchases_small.csv в одной папке с блокнотом. Вставь только содержимое блока ниже, без строк с тройными обратными кавычками. Сохрани файл в UTF-8.
id,platform,amount_rub,status,item_name
1,android,199,paid,Меч
2,ios,99,paid,"Зелье, большое"
3,android,199,refunded,Меч
4,android,0,paid,Подарок
5,ios,,paid,Неизвестная сумма
6,ios,50,paid,Монеты
В первой строке имена столбцов, в остальных шести покупки. В строке с id=5 между запятыми нет суммы: это пропуск. В строке с id=4 сумма явно равна нулю.
В CSV запятая внутри кавычек остаётся частью ячейки. Поэтому "Зелье, большое" это одно название, не два столбца. Обычное line.split(",") разрежет его неправильно: нужен разборщик CSV.
Где Python ищет файл
Запусти отдельную ячейку:
from pathlib import Path
folder = Path.cwd()
path = folder / "purchases_small.csv"
print(folder)
print(path.exists())
from pathlib import Path берёт инструмент Path из стандартного модуля Python, устанавливать его отдельно не нужно. Path.cwd() возвращает текущую рабочую папку процесса. В Jupyter она часто совпадает с папкой блокнота, но не обязана: проверяй напечатанный путь.
Оператор / между путём и именем файла соединяет части пути, а не делит числа. path.exists() проверяет наличие файла; ожидается True. Если получился False, сохрани CSV в напечатанную папку или задай точный путь, например Path("/Users/anna/reports/purchases_small.csv") на macOS. На Windows можно записать Path("C:/Users/Anna/reports/purchases_small.csv").
Path("purchases_small.csv") тоже работает, но относительный путь считается от текущей рабочей папки. При FileNotFoundError проверь имя, расширение и папку: расчёт тут ни при чём.
Прочитай словари, пока без чисел
Это продолжение ячейки, где определён path:
import csv
with open(path, newline="", encoding="utf-8") as file:
reader = csv.DictReader(file)
raw_rows = list(reader)
print(len(raw_rows))
print(raw_rows[1]["item_name"])
print(raw_rows[0]["amount_rub"])
Ответы: 6, Зелье, большое, 199. Последний ответ выглядит числом, но пока это текст. Проверка type(raw_rows[0]["amount_rub"]) покажет str.
По строкам:
import csvподключает стандартный модуль CSV.openоткрывает файл для чтения.encoding="utf-8"задаёт кодировку, чтобы кириллица читалась одинаково на разных компьютерах.newline=""оставляет обработку переводов строк модулю CSV. Это важно и при чтении, и при записи.with ... as file:даёт открытому файлу имяfile. Код с отступом работает с файлом, после выхода из блока файл закрывается, в том числе при ошибке.csv.DictReader(file)читает заголовок и превращает следующие записи в словари: имя столбца становится ключом.list(reader)собирает записи в список внутри блокаwith. После закрытия файла этот список можно обходить сколько угодно.
Здесь не нужен return: код стоит прямо в ячейке. В задаче ты поместишь чтение в функцию и вернёшь готовый список.
Строка «199» ещё не сумма
Продолжи после чтения файла:
rows = []
for raw in raw_rows:
row = dict(raw)
row["id"] = int(raw["id"])
if raw["amount_rub"] == "":
row["amount_rub"] = None
else:
row["amount_rub"] = float(raw["amount_rub"])
rows.append(row)
print(rows[0]["amount_rub"] + rows[1]["amount_rub"])
print(rows[3]["amount_rub"])
print(rows[4]["amount_rub"])
Ответы: 298.0, 0.0, None. int превращает текст идентификатора в целое число, float превращает текст суммы в число с дробной частью. dict(raw) создаёт отдельную копию словаря: исходные текстовые строки остаются в raw_rows.
Пустую строку нельзя передать в float: получится ValueError. Условие обрабатывает известный пропуск явно. Текст "0" не пустой, он превращается в 0.0. Не заменяй все пустые суммы нулями: Бран иначе не заметит неполную выгрузку.
Для учебного отчёта float хватит. В точных финансовых расчётах используют целые копейки или Decimal, потому что двоичные дроби не всегда представляют десятичные суммы точно. Здесь все суммы целые, поэтому сверка на 348 ₽ не требует округления.
урок из курса
Урок из курса «Аналитика данных с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.