Строки с кириллицей в Python: полное руководство для разработчика
Основные подходы к работе с русскими строками
Базовое решение – встроенная поддержка Unicode в Python 3. Все строки (тип str) хранят символы в виде Unicode-кодовых точек. Русские буквы (кириллица) входят в Unicode, поэтому для обычных операций (конкатенация, поиск, замена, форматирование) дополнительных действий не требуется.
Пример прямого использования:
text = "Привет, мир!"
print(text[::-1]) # "!рим ,тевирП"
print(len(text)) # 12текста русские python (работа с русским текстом в python)
При работе с внешними источниками (файлы, сеть, базы данных) необходимо согласовывать кодировку. Наиболее распространённая – UTF-8. Чтение файла с явным указанием кодировки:
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
Запись:
with open('output.txt', 'w', encoding='utf-8') as f:
f.write('Русский текст')
Типичная ошибка – опустить encoding при чтении файла, созданного в UTF-8. На Windows Python может использовать системную кодировку (например, cp1251) и получить UnicodeDecodeError. Решение – всегда явно задавать кодировку.
Проблема с консолью: вывод русских символов может отображаться кракозябрами. Настройка кодировки консоли в Windows через chcp 65001 или установка переменной окружения PYTHONIOENCODING=utf-8.
Как работать с русским текстом в кодировке CP1251 (Windows)?
Если документ сохранён в однобайтовой кодировке CP1251, при открытии указывается encoding='cp1251'. Аналогично для других кодировок (koi8-r, iso-8859-5).
with open('win_text.txt', 'r', encoding='cp1251') as f:
text = f.read()
# Далее работа в Unicode
print(text)
Смешивание кодировок в одном проекте приводит к UnicodeDecodeError или появлению знаков вопроса. Необходимо определить кодировку источника (библиотека chardet) или принудительно преобразовывать байты.
Как корректно сравнивать русские строки без учёта регистра?
Простейший способ – привести обе строки к нижнему регистру через .lower(). Но метод .lower() корректно обрабатывает кириллицу, включая «Ё» (преобразует к «ё»). Для более сложных случаев (например, турецкая I) используется .casefold() – более агрессивное приведение, подходящее для регистронезависимого сравнения.
s1 = "Столица"
s2 = "столицА"
print(s1.lower() == s2.lower()) # True
print(s1.casefold() == s2.casefold()) # True
Буква «ё» в .lower() преобразуется в «ё», а «Ё» – тоже в «ё», поэтому сравнение «Ель» и «ёлка» после lower не покажет равенства. Если нужно считать «ё» и «е» одинаковыми, следует предварительно заменить одну на другую:
s1 = "еж"
s2 = "ёж"
normalized = lambda s: s.lower().replace('ё', 'е').replace('Ё', 'е').replace('е', 'е')
print(normalized(s1) == normalized(s2)) # True
Как использовать регулярные выражения для поиска русских слов?
Библиотека re поддерживает Unicode, если флаг re.UNICODE включён (по умолчанию в Python 3). Диапазон для кириллицы: [а-яё], [А-ЯЁ]. Для учёта регистра используется re.IGNORECASE.
import re
pattern = r'[а-яёА-ЯЁ]+'
text = "Москва – столица РФ."
words = re.findall(pattern, text)
print(words) # ['Москва', 'столица', 'РФ']
Частая ошибка – написание [а-я] без буквы «ё». В стандартный диапазон «а-я» буква «ё» не входит, её нужно добавлять явно. Альтернатива – использовать символьный класс Unicode \p{Cyrillic} через модуль regex (сторонняя библиотека).
Как нормализовать русский текст: разные Unicode-представления буквы «ё»?
Буква «ё» может быть представлена как отдельный символ (U+0451) или как комбинация «е» (U+0435) с диакритическим знаком (U+0308). Модуль unicodedata позволяет привести к одной форме через normalize(). Форма NFC сворачивает составные символы, NFD разворачивает.
import unicodedata
text1 = "ё" # e + диакритика (два символа)
text2 = "ё" # один символ
print(unicodedata.normalize('NFC', text1) == unicodedata.normalize('NFC', text2)) # True
Поиск или сравнение строк, полученных из разных источников, может давать разные результаты из-за нормализации. Рекомендуется перед сравнением всегда приводить строки к одной нормализованной форме (чаще NFC).
Как работать с русскими именами файлов в Windows?
Современные версии Windows (NTFS) используют UTF-16, но Python для работы с путями использует кодировку, указанную в sys.getfilesystemencoding() (обычно utf-8 или mbcs). Для совместимости с русскими именами достаточно передавать пути как обычные Unicode-строки.
import os
filename = "документ.txt"
with open(filename, 'w', encoding='utf-8') as f:
f.write('содержимое')
print(os.listdir('.')) # список включает русские имена
Если имя файла получено извне и закодировано в cp1251, необходимо декодировать в Unicode: name = raw_bytes.decode('cp1251'). В обратную сторону при записи в файловую систему можно положиться на автоматическое кодирование через системную кодировку.
Расширенные примеры обработки русского текста
Автоматическое определение кодировки файла с русским текстом
Библиотека chardet (установка: pip install chardet) позволяет угадать кодировку по первым байтам. Пример чтения файла с неизвестной кодировкой:
import chardet
with open('unknown.txt', 'rb') as f:
raw = f.read(10000) # читаем начало файла
detected = chardet.detect(raw)
encoding = detected['encoding']
print(f"Определённая кодировка: {encoding}") # например, utf-8 или windows-1251
with open('unknown.txt', 'r', encoding=encoding, errors='replace') as f:
content = f.read()
print(content[:200])
Определённая кодировка: utf-8 Русский текст...
Ошибка UnicodeDecodeError при неверном определении. В таких случаях параметр errors='replace' заменяет нечитаемый символ на символ замены (обычно �), что позволяет продолжить обработку, но теряет часть данных.
Регистронезависимый поиск слов с учётом буквы «ё»
Для поиска всех вариантов слова, включая разное написание «ё», используется предварительная замена в шаблоне:
import re
text = "Ёжик под ёлкой. Ежик и елку не нашел."
# Заменим в тексте все е/ё на временный маркер, чтобы оба варианта находились
# Компактнее: пишем регулярное выражение [её] с флагом IGNORECASE
pattern = r'[её]жик'
matches = re.findall(pattern, text, re.IGNORECASE)
print(matches) # ['Ёжик', 'ёжик', 'ежик']
['Ёжик', 'ёжик', 'ежик']
Лемматизация русских слов с помощью pymorphy2
Библиотека pymorphy2 (установка: pip install pymorphy2) приводит слово к нормальной форме:
import pymorphy2
morph = pymorphy2.MorphAnalyzer()
words = ['книги', 'книгой', 'книга']
for w in words:
p = morph.parse(w)[0]
print(f"{w} -> {p.normal_form}")
книги -> книга книгой -> книга книга -> книга
Удаление стоп-слов из русского текста
Библиотека nltk содержит список русских стоп-слов. Пример фильтрации:
from nltk.corpus import stopwords
import nltk
nltk.download('stopwords')
russian_stopwords = set(stopwords.words('russian'))
text = "В лесу родилась ёлочка, в лесу она росла."
words = text.lower().split()
filtered = [w for w in words if w.strip('.,!?') not in russian_stopwords]
print(filtered)
['лесу', 'родилась', 'ёлочка', 'лесу', 'росла']
Некорректное удаление из-за пунктуации: необходимо очищать слова от знаков препинания. Лучше использовать re.findall(r'[а-яё]+', text) для получения списка чистых слов.
Транслитерация русских символов в латиницу
Библиотека transliterate (установка: pip install transliterate) преобразует кириллицу в латиницу по стандарту ISO 9 или другим:
from transliterate import translit
text = "Привет, мир!"
result = translit(text, reversed=True) # reversed=True – из кириллицы в латиницу
print(result)
Privet, mir!
Извлечение предложений, содержащих определённое русское слово
Пример с использованием регулярного выражения для разделения на предложения и фильтрации:
import re
text = "Москва – столица России. В ней живёт много людей. Столица является крупным городом."
sentences = re.split(r'(?<=[.!?])\s+', text)
keyword = "столица"
filtered = [s for s in sentences if keyword in s.lower()]
print(filtered)
['Москва – столица России.', 'Столица является крупным городом.']
Обработка русского текста в CSV-файлах
Модуль csv корректно работает с Unicode, если файл открыт с указанием кодировки UTF-8. Ошибки возникают при несовпадении кодировок в заголовке и данных:
import csv
data = [['Фамилия', 'Имя'], ['Иванов', 'Иван'], ['Сидорова', 'Мария']]
with open('people.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerows(data)
with open('people.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(', '.join(row))
Фамилия, Имя Иванов, Иван Сидорова, Мария
Если CSV-файл сохранён в кодировке Windows-1251, при открытии с encoding='utf-8' возникнет UnicodeDecodeError. Решение: определить фактическую кодировку (например, через chardet) и указать её.