При проверке выгрузки легко посчитать переводы строки и объявить число участников. Но комментарий в одной ячейке CSV может занимать несколько физических строк. Поэтому сначала разберите файл с его разделителем и правилами кавычек, а затем считайте записи данных.
Ниже специально созданный учебный текст с тремя вымышленными идентификаторами A01, A02, A03 и комментариями. Опрос не проводился. В нём выбран разделитель «;», двойная кавычка ограничивает поле, а удвоенная кавычка внутри такого поля передаёт одну кавычку. Заголовок состоит из двух имён: id и comment.
Полный CSV: перенос является частью первого комментария
id;comment
A01;"первая строка
вторая строка"
A02;"значение; с точкой"
A03;"он сказал ""да"""
Фрагмент показан целиком. Между словами «строка» и «вторая» стоит перевод строки внутри кавычек. В показанном тексте после A03 стоит ровно один завершающий перевод строки LF. Он завершает эту запись; дополнительной пустой строки в нашем примере нет. Точка с запятой внутри второго комментария относится к значению comment, а не создаёт третий столбец.
Что считаем | Результат в этом примере |
|---|---|
Физические строки текста | 5: заголовок, две строки первого комментария и ещё две записи. |
Логические записи вместе с заголовком | 4: один заголовок и три записи данных. |
Записи данных | 3: A01, A02, A03. |
Поля в каждой записи | 2: id и comment; перенос внутри comment не добавляет поле. |

Прочитайте CSV целиком одним парсером
В документации Python csv объяснено, что строка результата reader может охватывать несколько строк источника, а line_num учитывает прочитанные строки, не число записей. Для файлового объекта документация рекомендует newline="". Ниже для самодостаточного примера используется StringIO; при чтении с диска задайте также фактическую кодировку файла.
import csv
import io
text = ('id;comment\n'
'A01;"первая строка\nвторая строка"\n'
'A02;"значение; с точкой"\n'
'A03;"он сказал ""да"""\n')
reader = csv.reader(io.StringIO(text, newline=""),
delimiter=";", strict=True)
rows = list(reader)
header, data = rows[0], rows[1:]
assert len(header) == 2
assert header == ["id", "comment"]
assert all(len(row) == 2 for row in data)
assert len(data) == 3
assert data[0][1] == "первая строка\nвторая строка"
assert data[1][1] == "значение; с точкой"
assert data[2][1] == 'он сказал "да"'
print("physical_lines =", reader.line_num)
print("records_with_header =", len(rows))
print("data_records =", len(data))
for row in data:
print(row[0], repr(row[1]))
assert reader.line_num == 5
Ожидаемый вывод для приведённого учебного примера:
physical_lines = 5
records_with_header = 4
data_records = 3
A01 'первая строка\nвторая строка'
A02 'значение; с точкой'
A03 'он сказал "да"'
В repr первого комментария символы \n показывают один перевод строки внутри значения. Это представление строки Python: обратная косая черта и буква n не были отдельным текстом исходной ячейки. В последнем комментарии удвоенные кавычки исходного CSV прочитаны как обычные кавычки вокруг слова «да».
Почему split по строкам и разделителю здесь не подходит
Наивная операция | Что она исказит |
|---|---|
Считать каждую физическую строку участником | Первая запись будет ошибочно разделена на две. |
Разделять каждую строку по «;» | Внутренняя точка с запятой в A02 станет лишним полем. |
Удалить все кавычки до чтения | Исчезнут границы сложных полей и способ записи кавычки. |
Считать строку заголовка наблюдением | К трём учебным ID добавится строка с именами полей. |
strict=True заставляет парсер возбуждать исключение csv.Error при некорректном CSV по правилам этого парсера. Это не проверка научной корректности, уникальности ID и всех ограничений вашей схемы. Поэтому после разбора код отдельно проверяет два поля и точные имена заголовка, два поля каждой записи данных и учебные значения. Для чужого файла сначала определите диалект и ожидаемые столбцы, а не переносите настройки «;» и два поля автоматически.
Что записать в журнал проверки
- Какой файл и какая его версия прочитаны; исходник сохранён.
- Какие кодировка, разделитель и правила кавычек заданы.
- Отдельно указаны физические строки, записи с заголовком и записи данных.
- Проверено число полей и сохранение многострочного комментария.
- Число записей не объявлено числом людей без проверки единицы наблюдения и ID.
Для нашего файла итог: пять физических строк, четыре логические записи вместе с заголовком и три записи данных. Количество строк в текстовом редакторе не заменяет разбор структуры. После него типы полей, ведущие нули и пропуски проверяются отдельно — как в статье об импорте CSV с сохранением ID и десятичных дробей.
Если требуется подготовить собственную выгрузку к исследовательскому расчёту, можно обсудить консультацию по статистическому анализу. Заранее согласуйте исследовательский вопрос, структуру исходного файла и объём помощи. Успешное чтение файла само по себе не подтверждает достоверность измерений.