


CSV-файл лучше читать модулем csv, а не делить строки через split. Разделитель может оказаться внутри кавычек, а одна запись может занимать несколько строк. DictReader сопоставляет значения с названиями столбцов, но проверку обязательных полей и чисел нужно написать отдельно.
В учебном примере Mentoring.digital прочитаем список материалов. Это разбор формата и проверки входных данных, а не готовый импорт в рабочую базу.
Сохраните inventory.csv в UTF-8. В нашем договорённом формате ровно два столбца, разделитель ;, количество является неотрицательным целым числом:
name;quantity
"Кабель; USB";3
Переходник;0
Точка с запятой в названии первого предмета находится внутри кавычек и не создаёт третий столбец. У CSV нет единственного обязательного разделителя. Если ваш источник использует запятую или другую кодировку, измените настройки под этот источник, а не перебирайте их до исчезновения ошибки.
import csv
def load_inventory(path):
items = []
with open(path, encoding="utf-8-sig", newline="") as stream:
reader = csv.DictReader(stream, delimiter=";", strict=True)
fields = reader.fieldnames or []
if len(fields) != 2 or set(fields) != {"name", "quantity"}:
raise ValueError("Expected name and quantity columns")
for row in reader:
line = reader.line_num
if None in row or any(v is None for v in row.values()):
raise ValueError(f"Wrong column count near line {line}")
name = row["name"].strip()
if not name:
raise ValueError(f"Empty name near line {line}")
try:
quantity = int(row["quantity"])
except ValueError as error:
raise ValueError(f"Invalid quantity near line {line}") from error
if quantity < 0:
raise ValueError(f"Negative quantity near line {line}")
items.append({"name": name, "quantity": quantity})
return items
Вызов load_inventory("inventory.csv") возвращает список словарей. Для приведённого файла это названия «Кабель; USB» и «Переходник» с количествами 3 и 0. Исходник не изменяется, а при нарушении правил функция прекращает чтение с ошибкой.
newline="" оставляет обработку переводов строк модулю csv. Кодировка utf-8-sig принимает UTF-8 и убирает BOM в начале файла, если он присутствует. Это не универсальный способ читать любую кодировку: файл Windows-1251 нужно обрабатывать с его настоящей кодировкой.
В примере разрешён другой порядок двух столбцов, но не дополнительные или повторяющиеся заголовки. Названия сравниваются буквально. Если контракт допускает пробелы в заголовках или другой регистр, нормализацию нужно добавить явно и повторно проверить уникальность имён.
При лишних значениях DictReader по умолчанию помещает остаток под ключ None. При недостающих значениях заполняет соответствующие поля значением None. Поэтому код отдельно проверяет форму строки, прежде чем вызывать strip или int.
Параметр strict=True помогает обнаруживать ошибки CSV-разметки, но не проверяет смысл данных. Отрицательное количество, пустое название и слово вместо числа остаются правилами нашего приложения. Преобразование int допускает окружающие пробелы и знак числа; если входной формат строже, дополните эту проверку.
reader.line_num сообщает число прочитанных физических строк. Для записи с переносом внутри кавычек это не порядковый номер записи. Поэтому сообщение указывает область файла, а не обещает точный номер бизнес-записи.
Полностью пустые строки csv пропускает. Если важно учитывать их как ошибку, это отдельное требование. Пример также не объединяет одинаковые названия и не ищет дубли: правила идентификации записей нужно согласовать до импорта.
Следующий шаг на обучении Python на практических задачах может быть запись проверенных данных в новый файл. Для разбора реальной выгрузки с ментором по Python подготовьте обезличенный пример и ожидаемый результат. Не исправляйте исходные данные молча только ради успешного запуска.