Глава 15 · Python и файлы
Бинарные файлы и переносы строк
Не всё, что лежит в файле, — текст. И даже текст занимает на диске больше, чем кажется.
Бинарный режим
Добавьте b к режиму, чтобы работать с файлом как с чистыми
байтами, без какой-либо текстовой кодировки:
binarny_fajl.py
data = bytes([0, 1, 2, 3, 255])
with open("signal.bin", "wb") as f:
f.write(data)
with open("signal.bin", "rb") as f:
print(f.read()) # b'\\x00\\x01\\x02\\x03\\xff'
| Режим | Что получаем в Python | Пример |
|---|---|---|
"rt" / "r" | str (текст) | "Python" |
"rb" | bytes (двоичные данные) | b'Python' |
Не декодируйте произвольные бинарные данные как текст
PNG, JPEG или PDF не станут читаемыми от
open(..., encoding="utf-8") — это не текстовые данные, и попытка прочитать их как текст приведёт к ошибке или мусору. Для таких форматов используйте бинарный режим ("rb") или специализированную библиотеку для этого формата.Debug Lab 9: Бинарные данные, прочитанные как текст
bin_kak_text.py
data = bytes([0, 1, 2, 3, 255])
with open("signal.bin", "wb") as f:
f.write(data)
with open("signal.bin", "r", encoding="utf-8") as f:
print(f.read())
Traceback (most recent call last):
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 4: invalid start byte
Байт 0xff не образует корректный символ в UTF-8 — эти данные никогда и не были текстом. Файл нужно открывать в бинарном режиме ("rb"), а не текстовом.
Исправленный код
bin_pravilno.py
with open("signal.bin", "rb") as f:
print(f.read()) # b'\\x00\\x01\\x02\\x03\\xff'
Переносы строк и текстовый режим
\n внутри Python — универсальный перевод строки
На разных операционных системах исторически применяются разные последовательности для перевода строки на диске (например,
\r\n в файлах, созданных на Windows). Текстовый режим Python читает такие файлы в режиме универсальных переносов строк и отдаёт вам во всех случаях \n — вам не нужно обрабатывать оба варианта вручную в обычном текстовом коде.Символы против байтов — реальный пример
simvoly_vs_bajty.py
text = "Питон🐍"
print(len(text)) # 6 — количество символов
print(len(text.encode("utf-8"))) # 14 — количество байт в UTF-8
Длина текста ≠ размер файла в байтах
Кириллица и эмодзи занимают в UTF-8 несколько байт на один символ.
len(text) считает символы, а не байты — размер файла на диске может быть заметно больше, чем количество символов в строке.Практика: бинарные файлы и переносы строк
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки