Функция bytes в Python: синтаксис и примеры
Функция bytes в Python создает неизменяемую последовательность байтов, то есть целых чисел от 0 до 255. Такие объекты нужны для работы с бинарными файлами, сетью, хешированием и шифрованием. В статье разобраны все способы вызова bytes(), операции с байтами, перевод в строку и шестнадцатеричный вид, а также отличия от bytearray.

Содержание статьи
Синтаксис функции bytes()
Функция принимает до трех аргументов, и все они необязательные:
bytes(source=b'', encoding='utf-8', errors='strict')source- источник данных: строка, целое число, итерируемый объект с числами или объект с буферным интерфейсом;encoding- кодировка, обязательна, еслиsourceявляется строкой;errors- что делать с символами, которые нельзя закодировать:'strict','ignore','replace'и другие.
Результат зависит от типа первого аргумента:
| Аргумент source | Что получится | Пример |
|---|---|---|
| Строка | Байты строки в указанной кодировке | bytes('Hi', 'ascii') - b'Hi' |
| Целое число n | n нулевых байтов | bytes(3) - b'\x00\x00\x00' |
| Итерируемый объект чисел | По одному байту на каждое число 0-255 | bytes([72, 105]) - b'Hi' |
| bytearray, memoryview | Неизменяемая копия данных | bytes(bytearray(b'ok')) - b'ok' |
| Без аргументов | Пустой объект | bytes() - b'' |
Примеры создания байтов
Ниже основные варианты вызова с результатами. Обратите внимание на префикс b в выводе: так Python показывает объект bytes.
Из строки
Для строки кодировку нужно указать явно, иначе возникнет TypeError: string argument without an encoding. Вызов bytes(s, 'utf-8') равнозначен s.encode('utf-8'), второй вариант встречается в коде чаще.
message = 'Python is good'
print(bytes(message, 'utf-8')) # b'Python is good'
ru = bytes('Привет', 'utf-8')
print(ru) # b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'
print(len(ru)) # 12Латинские буквы в выводе видны как есть, а кириллица показана шестнадцатеричными кодами, потому что в UTF-8 каждая русская буква занимает два байта. Как выбрать кодировку и что делать с ошибками, подробно описано в статье про кодировку строк.
Из числа и списка
Целое число задает длину объекта, заполненного нулями. Это удобно, когда нужен буфер известного размера. Список или другой итерируемый объект превращается в байты поэлементно.
print(bytes(5)) # b'\x00\x00\x00\x00\x00'
print(bytes([1, 2, 3, 4, 5])) # b'\x01\x02\x03\x04\x05'
print(bytes(range(65, 70))) # b'ABCDE'
bytes([256]) # ValueError: bytes must be in range(0, 256)Байты со значениями печатных символов ASCII Python показывает буквами, остальные в виде \xNN. Внутри это одни и те же числа.
Литерал b''
Короткие байтовые строки удобно записывать литералом с префиксом b: b'GET / HTTP/1.1'. В литерале допустимы только ASCII-символы, остальные значения записывают через escape-последовательности, например b'\xff\x00'.
Операции с объектом bytes
Тип bytes поддерживает большинство операций последовательностей и многие методы строк. Главное отличие от строки: обращение по индексу возвращает число, а срез возвращает новый объект bytes.
data = b'Python'
print(data[0]) # 80 - код буквы P
print(data[:2]) # b'Py'
print(data + b'3') # b'Python3'
print(b'ab' * 3) # b'ababab'
print(b'th' in data) # True
print(list(data)) # [80, 121, 116, 104, 111, 110]
print(data.upper()) # b'PYTHON'
print(b'a,b,c'.split(b',')) # [b'a', b'b', b'c']Аргументы методов тоже должны быть байтами. Вызов data.split(',') со строкой вызовет TypeError, как и сложение b'a' + 'b'. Объект нельзя изменить: data[0] = 112 выдаст TypeError: 'bytes' object does not support item assignment.
Преобразование в строку, hex и число
Байты часто нужно показать человеку, передать в текстовом виде или собрать из них число. Для этого есть несколько встроенных методов.
raw = bytes('Привет', 'utf-8')
print(raw.decode('utf-8')) # Привет
print(b'Hello'.hex()) # 48656c6c6f
print(b'Hello'.hex(' ')) # 48 65 6c 6c 6f
print(bytes.fromhex('48 65 6c 6c 6f')) # b'Hello'
n = 1024
packed = n.to_bytes(2, 'big')
print(packed) # b'\x04\x00'
print(int.from_bytes(packed, 'big')) # 1024Метод decode() превращает байты обратно в текст и требует ту же кодировку, что использовалась при кодировании. Метод hex() выдает шестнадцатеричную строку, а fromhex() выполняет обратное преобразование, пробелы между парами символов допускаются. Пара to_bytes() и from_bytes() переводит целое число в байты и обратно, второй аргумент задает порядок байтов: 'big' или 'little'.
bytes и bytearray: в чем разница
У функции bytes() есть изменяемый аналог bytearray(). Аргументы у них одинаковые, а основная разница в изменяемости.
| Свойство | bytes | bytearray |
|---|---|---|
| Изменение элементов | Нельзя | Можно: ba[0] = 65 |
| append, extend, pop | Нет | Есть |
| Хешируемость | Да, может быть ключом словаря | Нет |
| Литерал | b'...' | Нет, только вызов функции |
| Когда использовать | Готовые данные, ключи, константы | Буфер, который собирается по частям |
Частая схема: данные накапливаются в bytearray, а в конце превращаются в bytes, чтобы их нельзя было случайно изменить.
buf = bytearray()
for chunk in (b'ab', b'cd'):
buf.extend(chunk)
result = bytes(buf)
print(result) # b'abcd'Где применяются байты
С объектами bytes вы встретитесь везде, где данные покидают программу или приходят извне:
- чтение и запись файлов в режимах
'rb'и'wb', подробнее в статье про бинарные файлы; - сетевые сокеты: методы
send()иrecv()работают только с байтами; - хеширование: функции модуля
hashlibпринимают байты, поэтому строку перед этим кодируют; - атрибут
response.contentв библиотеке requests содержит тело ответа в байтах; - кодирование в Base64 через модуль
base64.
import hashlib
password = 'secret'
digest = hashlib.sha256(password.encode('utf-8')).hexdigest()
print(digest[:16]) # 2bb80d537b1da3e3Полное описание типа и его методов есть в разделе Bytes Objects документации Python.
Частые вопросы
Короткие ответы на вопросы о функции bytes() и байтовых строках.
Почему print() выводит b'...' вместо текста?
Это представление объекта bytes, а не строки. Чтобы получить текст, вызовите decode() с нужной кодировкой: print(data.decode('utf-8')).
Чем bytes(s, 'utf-8') отличается от s.encode()?
Результат одинаковый. encode() короче и по умолчанию использует UTF-8, поэтому в коде его встречают чаще.
Почему data[0] возвращает число, а не b'P'?
Элемент последовательности bytes - целое число от 0 до 255. Чтобы получить объект из одного байта, используйте срез: data[0:1].
Как превратить байты в список чисел?
Передайте объект в list(): list(b'AB') вернет [65, 66].