#Что означает ошибка
UnicodeDecodeError
Python пытается прочитать байты как текст в UTF-8, а они на самом деле записаны в другой кодировке (чаще всего cp1251 для русских файлов из Windows, cp866 из консоли DOS, utf-16 из Excel/PowerShell) либо вообще не являются текстом (картинки, архивы, Excel). Число после byte (0xd0, 0xff, 0x98) намекает на тип проблемы: 0xff 0xfe — BOM UTF-16.
#Причины и решения
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Кодировка cp1251Файл создан в Windows-программе. | Байты 0xc0–0xff в тексте. | Откройте с encoding='cp1251'. |
Бинарный файлЧитается как текст файл .xlsx, .png, .zip. | Ошибка на первом же байте (0x89, 0x50). | Откройте в 'rb' и используйте нужную библиотеку. |
| BOMФайл начинается с маркера UTF-8/UTF-16. | Ошибка на 0xff или лишние символы \ufeff. | encoding='utf-8-sig' или utf-16. |
| Битые данныеФайл повреждён или обрезан. | Ошибка на середине файла. | Используйте errors='replace'. |
#Пошаговое решение
- Прочитайте текст ошибкиПрочитайте ошибку до конца и запишите имя файла, позицию
position Nи байт (0xc0и т. п.). Это означает, что выбранный декодер UTF-8 не смог интерпретировать байты; само по себе это не доказывает Windows-1251. Сделайте копию исходного файла, прежде чем пробовать перекодировку. В VS Code откройте файл через «Файл → Открыть файл», в строке состояния справа внизу посмотрите используемую кодировку и при необходимости выберите «Повторно открыть с кодировкой». Не сохраняйте файл с новой кодировкой, пока не убедились, что текст читается нормально. - Определите кодировкуЕсли происхождение файла известно, сначала выясните кодировку у отправителя или в документации источника: CSV из старой Windows может быть CP1251, но возможны KOI8-R, UTF-16 и другие варианты. Linux: команда
file -bi data.txtдаёт предположение о типе данных, не безусловно достоверную кодировку. Библиотекаchardetпо выборке тоже даёт лишь оценку: можно создать отдельное виртуальное окружение и использовать её только как подсказку. Сравните несколько русских фраз с ожидаемыми значениями; если пробная расшифровка даёт «кракозябры», вернитесь к копии. - Укажите кодировку явноЕсли подтверждена кодировка исходного текста, в строке чтения файла в Python укажите её явно: например,
with open('data.txt', 'r', encoding='cp1251') as f:и затем читайте изf. Путь замените путём реального файла, аcp1251— подтверждённой кодировкой. Для UTF-8 с подписью BOM подходитutf-8-sig, для обычного UTF-8 —utf-8. Сохраните изменённый скрипт и запустите прежнюю команду: ошибка должна исчезнуть, а кириллица отображаться без подмены букв; при иной ошибке проверьте, что читается тот же файл. - Не читайте бинарные файлы как текстЕсли файл на самом деле бинарный (
.xlsx, изображение, архив,.pdf), не открывайте его в текстовом режиме. Откройте свойства или проверьте расширение и первые байты на копии, затем используйте специализированную библиотеку:openpyxlдля XLSX,zipfileдля ZIP и т. п. Для просмотра сырых данных в Python используйтеopen('data.bin', 'rb'), где чтение возвращает байты. Если даже специализированный инструмент сообщает о повреждении структуры, уточните формат у автора или запросите исправленный файл — подбирать текстовую кодировку бессмысленно. - Обработайте повреждённые данныеПри единичных повреждённых байтах и необходимости получить приблизительный текст разрешается
errors='replace': неверные последовательности превращаются в символ замены�. Применяйте это только для просмотра/поиска, когда потеря части текста допустима;errors='ignore'незаметно удаляет символы и опасен для документов, идентификаторов, финансовых данных. Сначала подсчитайте количество замен и сохраните оригинал. Если требуется точная миграция, остановитесь и получите корректную копию или выясните настоящую кодировку. - Установите UTF-8 по умолчаниюНе применяйте
chcp 65001иPYTHONUTF8=1как способ починить файл в CP1251: они влияют на консоль и выбор кодировок по умолчанию, но не преобразуют байты источника. Если программа неправильно использует системную кодировку, укажитеencoding=в конкретном вызове чтения/записи и проверьте обе стороны обмена. В Windows PowerShell можно выполнитьpython -X utf8 script.pyдля диагностики поведения по умолчанию, но ошибка при чтении действительно не-UTF-8 файла останется. Не меняйте общесистемную локаль из-за одного CSV. - Перекодируйте файлЕсли нужно создать новую UTF-8-копию из подтверждённого CP1251, в терминале Linux/macOS выполните
iconv -f CP1251 -t UTF-8 data.txt > data-utf8.txt. Команда создаст отдельный файл и оставит исходный без изменений. Проверьте созданный текст в редакторе и сравните число строк; еслиiconvсообщает о недопустимой последовательности, не используйте опцию молчаливого пропуска символов. В Windows аналогичное преобразование выполните через «Сохранить с кодировкой» редактора, не перезаписывая исходный файл до проверки.
#Примеры кода
import chardet
with open('data.txt', 'rb') as f:
raw = f.read()
enc = chardet.detect(raw)['encoding']
print('Кодировка:', enc)
text = raw.decode(enc or 'utf-8', errors='replace')
# Явно указанная кодировка
with open('data.csv', encoding='cp1251', newline='') as f:
rows = f.read().splitlines()# Linux/macOS: оценка типа данных, затем перекодировка лишь после подтверждения CP1251:file -bi data.txticonv -f CP1251 -t UTF-8 data.txt > data-utf8.txtДля записи используйте тоже явную кодировку: open('out.txt', 'w', encoding='utf-8'); по умолчанию Windows использует cp1251, а Linux — utf-8, и скрипты ведут себя по-разному. Рекомендуется везде хранить текстовые файлы в UTF-8 без BOM. Подробнее — в .