Урок 3 из 8 · 20 мин · обновлено
Таблицы: чтение и запись Excel и CSV
Как читать и записывать таблицы в Python: CSV через модуль csv с правильной кодировкой и разделителем, файлы Excel через openpyxl — листы, строки, ячейки и новые книги.
CSV: самый простой формат таблиц
Кассовая программа «Канцмаркета» выгружает продажи в файл CSV — обычный текст, где каждая строка — строка таблицы, а значения разделены знаком. Откройте такой файл в блокноте, и увидите:
дата;товар;количество;цена
20.10.2026;Тетрадь 48 л.;12;95
20.10.2026;Ручка гелевая;30;45
21.10.2026;Тетрадь 48 л.;8;95
21.10.2026;Маркер;5;120
Две особенности, на которых часто спотыкаются новички:
- разделитель. В английских программах — запятая, в русских — обычно точка с запятой, потому что запятая занята дробными числами;
- кодировка. Русские буквы в файле записаны в какой-то кодировке. Сейчас это почти всегда UTF-8. Если файл сохранял Excel, в начале стоит невидимая метка, поэтому читать его надёжнее с кодировкой
utf-8-sig.
Читаем CSV
В Python есть встроенный модуль csv. Удобнее всего DictReader: он превращает каждую строку в словарь, где ключи — заголовки столбцов.
import csv
total = 0
with open("продажи_магазин1.csv", encoding="utf-8-sig", newline="") as f:
for row in csv.DictReader(f, delimiter=";"):
amount = int(row["количество"]) * int(row["цена"])
total += amount
print(row["дата"], row["товар"], amount)
print("Выручка:", total)
20.10.2026 Тетрадь 48 л. 1140
20.10.2026 Ручка гелевая 1350
21.10.2026 Тетрадь 48 л. 760
21.10.2026 Маркер 600
Выручка: 3850
Обратите внимание на int(): из CSV все значения приходят строками. Без превращения в число "12" * 2 даст не 24, а "1212". Для дробных чисел используйте float(), а запятую в «45,50» сначала замените на точку: float(value.replace(",", ".")).
with open(...) сам закроет файл, когда блок закончится. newline="" модуль csv просит указывать всегда — так он правильно обрабатывает переносы строк.
Записываем CSV
Запись устроена зеркально — через DictWriter:
import csv
rows = [
{"товар": "Тетрадь 48 л.", "остаток": 140},
{"товар": "Маркер", "остаток": 18},
]
with open("остатки.csv", "w", encoding="utf-8-sig", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["товар", "остаток"], delimiter=";")
writer.writeheader()
writer.writerows(rows)
Получится файл, который Excel откроет сразу с правильными колонками и русскими буквами:
товар;остаток
Тетрадь 48 л.;140
Маркер;18
Excel через openpyxl
Магазины присылают продажи уже в Excel — файлы .xlsx. Их читает библиотека openpyxl, которую мы поставили в уроке 1. Устройство файла Excel повторяет то, что вы видите в программе:
- книга (workbook) — весь файл;
- лист (worksheet) — вкладка внизу;
- ячейка (cell) — пересечение строки и столбца, например
B2.
Лист «Продажи» в файле второго магазина устроен так же, как CSV выше: в строке 1 заголовки «Дата», «Товар», «Количество», «Цена» в столбцах A–D, со строки 2 — продажи, по одной в строке.
Читаем его:
from openpyxl import load_workbook
wb = load_workbook("магазин_2.xlsx")
ws = wb["Продажи"]
for date, product, qty, price in ws.iter_rows(min_row=2, values_only=True):
print(date, product, qty * price)
20.10.2026 Ручка гелевая 1800
21.10.2026 Блокнот А5 2100
22.10.2026 Тетрадь 48 л. 1425
wb["Продажи"]— лист по названию; первый лист книги можно взять какwb.active;min_row=2пропускает строку заголовков;values_only=Trueотдаёт значения, а не объекты ячеек, поэтому строку можно сразу разложить по переменным.
В отличие от CSV, числа из Excel приходят уже числами: qty * price работает без int(). Даты в нашем файле записаны текстом. Если в ячейке настоящая дата Excel, openpyxl вернёт объект datetime — как с ним работать, разберём в уроке 5.
К отдельной ячейке обращаются по адресу: ws["B2"].value вернёт «Ручка гелевая». Записать значение так же просто: ws["E1"] = "Сумма", после чего книгу нужно сохранить: wb.save("магазин_2.xlsx").
Попробуйте сами. Дополните скрипт для CSV так, чтобы он считал выручку не общей суммой, а по каждому товару, и печатал результат. Подсказка: понадобится словарь.
Решение
import csv
by_product = {}
with open("продажи_магазин1.csv", encoding="utf-8-sig", newline="") as f:
for row in csv.DictReader(f, delimiter=";"):
amount = int(row["количество"]) * int(row["цена"])
product = row["товар"]
by_product[product] = by_product.get(product, 0) + amount
for product, amount in by_product.items():
print(product, amount)
Тетрадь 48 л. 1900
Ручка гелевая 1350
Маркер 600
by_product.get(product, 0) возвращает уже накопленную сумму или 0, если товар встретился впервые. Этот приём — основа отчёта, который мы соберём в следующем уроке.
Мини-тест · 4 вопроса
Проверьте себя
Выберите вариант, который кажется вам правильным. В конце вы увидите свой результат и объяснение к каждому вопросу.
-
CSV из кассовой программы открылся в Python одной колонкой: «20.10.2026;Тетрадь 48 л.;12;95». Что поправить?
По умолчанию модуль csv ждёт запятую. В русских программах разделитель часто точка с запятой — его нужно указать явно.
-
row["количество"] из CSV равно "12". Почему row["количество"] * 2 даёт "1212"?
CSV — текст, поэтому все значения — строки. Чтобы считать, превратите их в числа: int(row["количество"]).
-
Что делает ws.iter_rows(min_row=2, values_only=True)?
min_row=2 пропускает строку заголовков, а values_only=True возвращает сами значения вместо объектов ячеек.
-
Зачем при записи CSV указывают encoding="utf-8-sig"?
utf-8-sig добавляет в начало файла невидимую метку. По ней Excel понимает, что файл в UTF-8, и не превращает кириллицу в «кракозябры».