Работа с байтами: префикс b в Python 3
Префикс b для строк в Python 3
Как создать байтовый литерал из ASCII символов?
Простейший способ получить объект bytes в Python 3 - использовать префикс b перед строковым литералом, заключенным в кавычки. Например:
data = b'hello'
print(data) # b'hello'
print(type(data)) # <class 'bytes'>
print(len(data)) # 5использование b в python (использование префикса b в python)
Каждый символ внутри литерала b'...' интерпретируется как ASCII-код и занимает ровно один байт. Такой литерал может содержать цифры, латинские буквы, знаки препинания и некоторые escape-последовательности (\n, \x, \t и т.д.).
Типичная ошибка: попытка поместить в b'...' символы, не входящие в диапазон ASCII (например, кириллица). Это приведет к SyntaxError:
# b'привет' # SyntaxError: bytes can only contain ASCII literal characters.Str b a в python 3 (префикс b для строк в python 3)
Решение: использовать кодирование обычной строки (см. варианты ниже).
Цель: быстрое создание байтовых данных для низкоуровневых операций - работа с сетевыми протоколами, бинарными файлами, криптографией.
Вариант 1: Преобразование строки через encode()
Как преобразовать обычную строку (str) в байты с явным указанием кодировки?
Метод encode() вызывается у строки и возвращает объект bytes. Кодировку нужно задавать вторым аргументом (по умолчанию utf-8).
text = "Привет, мир!"
data = text.encode('utf-8')
print(data) # b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82, \xd0\xbc\xd0\xb8\xd1\x80!'
print(len(data)) # 19 (каждый русский символ занимает 2 байта в UTF-8)Python b string (строки с префиксом b в python)
Такой способ подходит для любых символов, в том числе Unicode. Важно помнить: при декодировании нужно использовать ту же кодировку.
Типичная ошибка: использование encode() без указания кодировки, когда байты потом читаются с другой кодировкой. Это приводит к UnicodeDecodeError или искажению.
# Кодирование в utf-8, а декодирование в cp1251
original = "Привет"
encoded = original.encode('utf-8')
try:
decoded = encoded.decode('cp1251')
except UnicodeDecodeError as e:
print(f"Ошибка: {e}")Python b format (формат b в python)
Ошибка: 'charmap' codec can't decode byte 0x9f in position 0: character maps to <undefined>
Решение: всегда передавать кодировку явно и согласовывать её на всех этапах.
Вариант 2: Конструктор bytes()
Каким образом создать объект bytes из строки или последовательности чисел?
Конструктор bytes() может принимать строку с указанием кодировки, итератор целых чисел (0-255), число (создаст нулевые байты) или байтоподобный объект.
# Из строки
b1 = bytes("abc", "ascii")
print(b1) # b'abc'
# Из списка чисел (коды символов)
b2 = bytes([97, 98, 99])
print(b2) # b'abc'
# Из целого числа (создает последовательность нулевых байтов)
b3 = bytes(5)
print(b3) # b'\x00\x00\x00\x00\x00'
Конструктор удобен для создания байтов из явно заданных значений, например, для формирования бинарных заголовков.
Типичная ошибка: передача строки без кодировки - получим TypeError.
# bytes("abc") # TypeError: string argument without an encoding
Решение: всегда указывать кодировку вторым аргументом.
Вариант 3: Экранирование hex в префиксе b
Как записать байты с произвольными значениями, не все из которых соответствуют читаемым символам?
Внутри b'...' можно использовать escape-последовательность \xHH, где HH - шестнадцатеричный код байта.
data = b'\x48\x65\x6c\x6c\x6f' # H e l l o
print(data.decode('ascii')) # Hello
Также доступны другие escape-последовательности: \n (новая строка, байт 0x0A), \t (табуляция, 0x09), \\ (обратная косая черта).
Этот способ часто применяют для записи бинарных протоколов, когда нужно точно указать байтовые значения.
Вариант 4: Изменяемые байты - bytearray
Как создать изменяемую последовательность байтов, чтобы модифицировать её после создания?
Тип bytearray похож на bytes, но элементы можно изменять. Создаётся так же: через префикс ba (не путать!), литерала с префиксом ba нет; используется конструктор bytearray(b'...') или bytearray(5).
ba = bytearray(b'Hello')
print(ba[0]) # 72 (код 'H')
ba[0] = 104 # меняем на 'h'
print(ba) # bytearray(b'hello')
# Преобразование обратно в bytes
b = bytes(ba)
print(b) # b'hello'
Используется, когда нужна изменяемая память - например, при построении пакета данных по частям.
Расширенные примеры работы с префиксом b и байтами
Пример 1. Комбинирование escape-последовательностей
data = b'Line1\nLine2\tTabbed\x00Null'
print(data)
print('As list:', list(data))
b'Line1\nLine2\tTabbed\x00Null' As list: [76, 105, 110, 101, 49, 10, 76, 105, 110, 101, 50, 9, 84, 97, 98, 98, 101, 100, 0, 78, 117, 108, 108]
Пример 2. Преобразование строки в байты с разными кодировками
text = "Python 3 работает с Unicode"
utf8 = text.encode('utf-8')
cp1251 = text.encode('cp1251')
print('UTF-8:', utf8)
print('CP1251:', cp1251)
print('Длина UTF-8:', len(utf8))
print('Длина CP1251:', len(cp1251))
UTF-8: b'Python 3 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\xd0\xb5\xd1\x82 \xd1\x81 Unicode' CP1251: b'Python 3 \xf0\xe0\xe1\xee\xf2\xe0\xe5\xf2 \xf1 Unicode' Длина UTF-8: 27 Длина CP1251: 22
Пример 3. Чтение и запись в бинарный файл
# Запись байтов в файл
with open('data.bin', 'wb') as f:
f.write(b'\x00\x01\x02\xff')
# Чтение обратно
with open('data.bin', 'rb') as f:
content = f.read()
print('Прочитано:', content)
print('В виде чисел:', list(content))
Прочитано: b'\x00\x01\x02\xff' В виде чисел: [0, 1, 2, 255]
Пример 4. Отправка и получение байтов через сокет (упрощённо)
import socket
# Серверная часть (для демонстрации)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 65432))
server.listen(1)
# Клиентская часть (в реальном коде в разных потоках)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 65432))
conn, addr = server.accept()
# Отправка байтов сервером
conn.sendall(b'Hello from server')
# Приём клиентом
data = client.recv(1024)
print('Клиент получил:', data)
conn.close()
server.close()
client.close()
Клиент получил: b'Hello from server'
Пример 5. Обработка ошибок декодирования с разными стратегиями
broken = b'\xff\xfe\x00' # некорректная UTF-8
print('strict:', end=' ')
try:
broken.decode('utf-8')
except UnicodeDecodeError as e:
print(e)
print('ignore:', broken.decode('utf-8', errors='ignore'))
print('replace:', broken.decode('utf-8', errors='replace'))
print('backslashreplace:', broken.decode('utf-8', errors='backslashreplace'))
strict: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte ignore: replace: ��� backslashreplace: \xff\xfe\x00
Пример 6. Срезы и конкатенация байтов
b1 = b'Hello'
b2 = b' World'
b3 = b1 + b2
print('Конкатенация:', b3)
print('Срез [1:4]:', b3[1:4])
print('Поиск подстроки:', b'World' in b3)
Конкатенация: b'Hello World' Срез [1:4]: b'ell' Поиск подстроки: True
Пример 7. Bytes как последовательность целых
data = b'\x41\x42\x43'
for byte in data:
print(byte, end=' ')
print()
# Список целых
print(list(data)) # [65, 66, 67]
65 66 67 [65, 66, 67]
Пример 8. Использование bytearray для модификации
ba = bytearray(b'\x00\x01\x02\x03')
print('До:', ba)
ba[1] = 0xff
print('После:', ba)
# Добавление нового элемента (расширение)
ba.append(10)
print('После append:', ba)
# Удаление по индексу
del ba[0]
print('После удаления первого:', ba)
До: bytearray(b'\x00\x01\x02\x03') После: bytearray(b'\x00\xff\x02\x03') После append: bytearray(b'\x00\xff\x02\x03\n') После удаления первого: bytearray(b'\xff\x02\x03\n')