При проверке выгрузки легко посчитать переводы строки и объявить число участников. Но комментарий в одной ячейке 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: 5 физических строк, 4 логические записи вместе с одним заголовком, 3 записи данных A01–A03 по 2 поля.
Авторская учебная схема, все ID и комментарии вымышлены. Перенос строки внутри комментария не создаёт нового наблюдения: в этом файле 5 физических строк, 4 логические записи с заголовком и 3 записи данных. Это не снимок программы.

Прочитайте 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 и десятичных дробей.

Если требуется подготовить собственную выгрузку к исследовательскому расчёту, можно обсудить консультацию по статистическому анализу. Заранее согласуйте исследовательский вопрос, структуру исходного файла и объём помощи. Успешное чтение файла само по себе не подтверждает достоверность измерений.