Количество строк в Python: от простого к эффективному

Задача «посчитать строки» в Python встречается в двух контекстах: строки в файле и строки в строковой переменной. В обоих случаях решение укладывается в одну-две строчки кода, но выбор способа зависит от размера данных. Для файла в 100 строк подойдёт любой вариант. Для файла в 10 ГБ — только тот, что не загружает его целиком в память.

Ниже — пять рабочих способов с примерами кода, сравнением по скорости и памяти, и рекомендацией, какой когда использовать.

Способ 1: readlines() + len()

Самый очевидный вариант. Читаем все строки файла в список, считаем длину списка:

with open("data.txt", "r", encoding="utf-8") as f:
    line_count = len(f.readlines())

print(line_count)

Как это работает

readlines() читает весь файл и возвращает список, где каждый элемент — одна строка (включая символ
на конце). len() возвращает количество элементов в списке.

Когда использовать

  • Файл небольшой (до нескольких мегабайт)
  • Вам всё равно нужны сами строки для дальнейшей обработки

Минус

Весь файл загружается в память. Файл в 2 ГБ займёт ≈2 ГБ оперативки — и скрипт может упасть с MemoryError.

Способ 2: генераторное выражение + sum()

Элегантный однострочник, который не загружает файл целиком в память:

with open("data.txt", "r", encoding="utf-8") as f:
    line_count = sum(1 for _ in f)

print(line_count)

Как это работает

Файловый объект в Python — итератор. Цикл for _ in f перебирает строки по одной, не создавая список в памяти. Генераторное выражение (1 for _ in f) отдаёт единицу на каждую строку, а sum() складывает их.

Когда использовать

  • Файлы любого размера — потребление памяти минимальное и постоянное
  • Нужен только подсчёт, сами строки не важны

Это рекомендуемый универсальный способ для большинства задач.

Способ 3: enumerate()

Вариация предыдущего способа, полезная, когда нужно одновременно считать строки и что-то делать с каждой:

with open("data.txt", "r", encoding="utf-8") as f:
    for count, line in enumerate(f, start=1):
        pass  # здесь можно обрабатывать каждую строку

print(count)

Как это работает

enumerate(f, start=1) нумерует строки начиная с 1. После завершения цикла переменная count содержит номер последней строки — то есть общее количество.

Нюанс

Если файл пустой, переменная count не будет создана и код упадёт с NameError. Безопасный вариант:

count = 0
with open("data.txt", "r", encoding="utf-8") as f:
    for count, _ in enumerate(f, start=1):
        pass
print(count)  # 0 для пустого файла

Способ 4: splitlines() для строковых переменных

Если строки нужно посчитать не в файле, а в обычной строковой переменной:

text = """Первая строка
Вторая строка
Третья строка"""

line_count = len(text.splitlines())
print(line_count)  # 3

Почему splitlines(), а не split(«\n»)

splitlines() корректно обрабатывает все виды переносов строк:
(Unix),
(Windows),
(старый Mac). А split("
")
— только
. Кроме того, splitlines() не создаёт лишний пустой элемент, если строка заканчивается переносом.

Тот же подход работает с pathlib:

from pathlib import Path

line_count = len(Path("data.txt").read_text(encoding="utf-8").splitlines())

Компактно, но загружает файл целиком — подходит только для небольших файлов.

Способ 5: subprocess + wc (Linux/macOS)

На Unix-системах можно использовать утилиту wc -l, которая считает строки на уровне ОС — это самый быстрый способ для больших файлов:

import subprocess

result = subprocess.run(["wc", "-l", "data.txt"], capture_output=True, text=True)
line_count = int(result.stdout.split()[0])
print(line_count)

Когда использовать

  • Linux или macOS
  • Огромные файлы (гигабайты и больше)
  • Скорость критична

Минус

Не работает на Windows без WSL или Cygwin. Для кроссплатформенного кода лучше способ 2.

Сравнение способов

Способ Память Скорость Кроссплатформенность Когда выбирать
len(f.readlines()) Весь файл в RAM Быстро для малых файлов Да Малые файлы + нужны сами строки
sum(1 for _ in f) Постоянная, минимальная Быстро Да Универсальный выбор
enumerate() Постоянная, минимальная Быстро Да Подсчёт + обработка строк
splitlines() Весь текст в RAM Быстро для малых строк Да Строковые переменные, pathlib
wc -l Минимальная Самый быстрый Только Unix Гигабайтные файлы на Linux/macOS

Практические примеры

Подсчёт непустых строк

with open("data.txt", "r", encoding="utf-8") as f:
    non_empty = sum(1 for line in f if line.strip())

print("Непустых строк:", non_empty)

Подсчёт строк, содержащих определённое слово

with open("log.txt", "r", encoding="utf-8") as f:
    errors = sum(1 for line in f if "ERROR" in line)

print("Строк с ошибками:", errors)

Подсчёт строк кода в Python-файле (без пустых и комментариев)

with open("script.py", "r", encoding="utf-8") as f:
    code_lines = sum(
        1 for line in f
        if line.strip() and not line.strip().startswith("#")
    )

print("Строк кода:", code_lines)

Подсчёт строк во всех .txt файлах папки

from pathlib import Path

total = 0
for file in Path("./data").glob("*.txt"):
    with open(file, "r", encoding="utf-8") as f:
        total += sum(1 for _ in f)

print("Всего строк во всех файлах:", total)

FAQ

Для обычных файлов (до сотен МБ) разница между sum(1 for _ in f) и len(f.readlines()) минимальна — доли секунды. Для гигабайтных файлов на Linux/macOS быстрее всего wc -l через subprocess, потому что утилита написана на C и работает на уровне ОС.

Да. Способ 2 (sum(1 for _ in f)) читает файл построчно — в памяти находится только одна строка в каждый момент. Способ 5 (wc -l) вообще не читает файл в Python — это делает системная утилита.

Это бывает при смешанных переносах строк (когда в одном файле есть и
, и
, и
). splitlines() распознаёт все виды переносов, а итератор файла — только
(в текстовом режиме Python конвертирует
в
, но одиночные
может пропустить). Если результаты расходятся — проверьте кодировку и формат переносов в файле.

Добавьте условие if line.strip() в генераторное выражение: sum(1 for line in f if line.strip()). Метод strip() убирает пробелы и переносы — пустая строка после него превращается в пустую строку "", которая в булевом контексте даёт False.

Для простых случаев (однострочные комментарии #): sum(1 for line in f if line.strip() and not line.strip().startswith("#")). Для точного подсчёта с учётом многострочных строк и docstring используйте модуль ast или утилиту pygount.
Оцените статью
Добавить комментарий