Подтвердить что ты не робот

Что такое Python bytestring?

Что такое Python bytestring?

Все, что я могу найти, - это темы о том, как кодировать для байта или декодирования до ascii или utf-8. Я пытаюсь понять, как это работает под капотом. В обычной строке ASCII это массив или список символов, и каждый символ представляет значение ASCII от 0 до 255, так что, как вы знаете, какой символ представлен числом. В Unicode это 8- или 16-байтовое представление для символа, которое сообщает вам, какой символ он имеет.

Итак, что такое bytestring? Как Python знает, какие символы представлять в качестве чего? Как это работает под капотом? Поскольку вы можете печатать или даже возвращать эти строки, и он показывает вам строковое представление, я не совсем понимаю его...

Хорошо, поэтому моя точка определенно пропущена здесь. Мне сказали, что это неизменная последовательность байтов без какой-либо конкретной интерпретации.

Последовательность байтов. Хорошо, скажем, один байт:
'a'.encode() возвращает b'a'.

Прост достаточно. Почему я могу прочитать a?

Скажем, я получил значение ASCII для a, выполнив следующее:
printf "%d" "'a"

Он возвращает 97. Хорошо, хорошо, целочисленное значение для символа ASCII a. Если мы интерпретируем 97 как ASCII, скажем, в C char, тогда получаем букву a. Справедливо. Если мы преобразуем представление байта в биты, мы получим следующее:

01100001

2 ^ 0 + 2 ^ 5 + 2 ^ 6 = 97. Прохладный.

Итак, почему 'a'.encode() возвращает b'a' вместо 01100001?
Если он без конкретной интерпретации, не должен ли он возвращать что-то вроде b'01100001'?
Он кажется, как будто он интерпретирует его как ASCII.

Кто-то упомянул, что он вызывает __repr__ в байтовой строке, поэтому он отображается в форме, удобной для человека. Однако, даже если я делаю что-то вроде:

with open('testbytestring.txt', 'wb') as f:
    f.write(b'helloworld')

Он по-прежнему будет вставлять helloworld в качестве регулярной строки в файл, а не как последовательность байтов... Так что это байтовая строка в ASCII?

4b9b3361

Ответ 1

Python не знает, как представить байтовую строку. Это точка.

Когда вы выводите символ со значением 97 в почти любое окно вывода, вы получите символ "a", но не являющийся частью реализации; это просто вещь, которая оказывается локально правдой. Если вы хотите кодировать, вы не используете bytestring. Если вы используете bytestring, у вас нет кодировки.

Ваша статья о файлах .txt показывает, что вы неправильно поняли, что происходит. Вы видите, что в текстовых файлах тоже нет кодировки. Это всего лишь серия байтов. Эти байты переводятся в буквы текстовым редактором, но нет никакой гарантии, что кто-то другой, открывающий ваш файл, увидит то же самое, что и вы, если вы отклонитесь от общего набора символов ASCII.

Ответ 2

Это распространенное заблуждение, что текст - ascii или utf8 или cp1252, и поэтому байты - это текст.

Текст - это только текст, в котором изображения представляют собой только изображения. Вопрос хранения текста или изображений на диске - это вопрос кодирования данных в последовательность байтов. Существует множество способов кодирования изображений в байтах: Jpeg, png, svg, а также множество способов кодирования текста, ascii, utf8 или cp1252.

Как только кодирование произошло, байты - это просто байты. Байты больше не являются изображениями, они забыли цвета, которые они имеют в виду; хотя декодер формата изображения может восстановить эту информацию. Байты так же забыли письма, которыми они раньше были. Фактически, байты не помнят, что они были изображениями или текстом вообще. Только внедиапазонные знания (имя файла, заголовки медиа и т.д.) Могут угадать, что должны означать эти байты, и даже это может быть неверно (в случае повреждения данных)

поэтому в python (py3) у нас есть два типа для вещей, которые в противном случае выглядели бы одинаково; Для текста у нас есть str, который знает его текст; он знает, какие буквы он должен иметь в виду. Он не знает, какие байты могут быть, поскольку буквы не являются байтами. У нас также есть bytestring, который не знает, есть ли он текст или изображения или какие-либо другие данные.

Эти два типа внешне похожи друг на друга, поскольку они являются как последовательностями вещей, но и то, что они представляют собой последовательности, совершенно разные.

Реализовано, str хранится в памяти как UCS-?, где? определена реализация, это могут быть UCS4, UCS2 или UCS1, в зависимости от параметров времени компиляции и какие кодовые точки присутствуют в представленной строке.


изменить "но почему"?

Некоторые вещи, которые похожи на текст, на самом деле определяются другими терминами. Действительно хороший пример этого - множество интернет-протоколов мира. Например, HTTP - это "текстовый" протокол, который на самом деле определяется с использованием синтаксиса ABNF, распространенного в RFC. Эти протоколы выражаются в терминах октетов, а не символов, хотя также может быть предложено неформальное кодирование:

2.3. Значения терминалов

Правила разрешают в строку значений терминалов, иногда называемых персонажи. В ABNF символ является просто неотрицательным целым числом.
В определенных контекстах конкретное отображение (кодирование) значений в будет указан набор символов (такой как ASCII).

Это различие важно, потому что невозможно отправить текст через Интернет, единственное, что вы можете сделать, это отправить байты. говоря "текст, но в кодировке" foo ", делает формат намного сложнее, так как клиенты и серверы должны теперь каким-то образом вычислить бизнес кодирования самостоятельно, надеюсь, таким же образом, поскольку они должны в конечном счете передавать данные в виде байтов так или иначе. Это вдвойне бесполезно, так как эти протоколы в любом случае редко относятся к обработке текста, и это только удобство для разработчиков. Ни владельцы серверов, ни конечные пользователи не заинтересованы в чтении слов Transfer-Encoding: chunked, если и сервер, и браузер понимают это правильно.

Для сравнения, при работе с текстом вам все равно, как это кодируется. Вы можете выразить "Heävy Mëtal Ümlaüts" любым удобным вам способом, кроме "Heδvy Mλtal άmlaόts"


различные типы дают вам способ сказать "это значение" означает "текст" или "байты".

Ответ 3

Как следует из названия, Python3 bytestring (или просто str в Python 2.7) представляет собой строку байтов. И, как уже отмечали другие, он неизменен.

Это отличается от Python3 str (или, более конкретно, unicode в Python 2.7), который является Строка абстрактных символов Unicode (например, UTF-32, хотя Python3 добавляет причудливое сжатие под капот, чтобы уменьшить фактический объем памяти, аналогичный UTF-8, возможно, даже в более общем виде).

Существуют три способа "интерпретации" этих байтов. Вы можете посмотреть на числовое значение элемента, например так:

>>> ord(b'Hello'[0])  # Python 2.7 str
72
>>> b'Hello'[0]  # Python 3 bytestring
72

Или вы можете указать Python отправлять один или несколько элементов на терминал (или файл, устройство, сокет и т.д.) в виде 8-битных символов, например:

>>> print b'Hello'[0] # Python 2.7 str
H
>>> import sys
>>> sys.stdout.buffer.write(b'Hello'[0:1]) and None; print() # Python 3 bytestring
H

Как намекнул Джек, в этом последнем случае это ваш терминал, интерпретирующий персонаж, а не питон.

Наконец, как вы видели в своем собственном исследовании, вы также можете заставить Python интерпретировать bytestring. Например, вы можете создать абстрактный объект unicode, например, в Python 2.7:

>>> u1234 = unicode(b'\xe1\x88\xb4', 'utf-8')
>>> print u1234.encode('utf-8') # if terminal supports UTF-8
ሴ
>>> u1234
u'\u1234'
>>> print ('%04x' % ord(u1234))
1234
>>> type(u1234)
<type 'unicode'>
>>> len(u1234)
1
>>> 

Или как в Python 3:

>>> u1234 = str(b'\xe1\x88\xb4', 'utf-8')
>>> print (u1234) # if terminal supports UTF-8 AND python auto-infers
ሴ
>>> u1234.encode('unicode-escape')
b'\\u1234'
>>> print ('%04x' % ord(u1234))
1234
>>> type(u1234)
<class 'str'>
>>> len(u1234)
1

(и я уверен, что отток синтаксиса между Python2.7 и Python3 вокруг строки, строки и юникода был связан с продолжающейся популярностью Python2.7. Я полагаю, что когда Python3 был изобретен, они не ' пока не понимаю, что все станет UTF-8, и поэтому вся суета об абстракции была излишней)

Но абстракция юникода не происходит автоматически, если вы этого не хотите. Суть bytestring в том, что вы можете напрямую получить байты. Даже если ваша строка является последовательностью UTF-8, вы все равно можете получить доступ к байту в последовательности:

>>> len(b'\xe1\x88\xb4')
3
>>> b'\xe1\x88\xb4'[0]
'\xe1'

и это работает как в Python2.7, так и в Python3, с той разницей, что в Python2.7 у вас есть str, а в Python3 у вас есть bytestring.

Вы также можете делать другие замечательные вещи с bytestring, например, знать, поместятся ли они в зарезервированное пространство в файле, отправлять их прямо через сокет, правильно вычислять поле HTTP content-length и избегать ошибки Python 8260. Короче говоря, используйте bytestring, когда ваши данные обрабатываются и хранятся в байтах.

Ответ 4

Объекты Bytes являются неизменяемыми последовательностями одиночных байтов. docs имеют очень хорошее объяснение того, что они собой представляют и как их использовать.