Вопрос-Ответ

What is the difference between a string and a byte string?

В чем разница между строкой и строкой байтов?

Я работаю с библиотекой, которая возвращает "строку байтов" (bytes), и мне нужно преобразовать это в строку.

Есть ли на самом деле разница между этими двумя вещами? Как они связаны и как я могу выполнить преобразование?

Переведено автоматически
Ответ 1

Единственное, что может хранить компьютер, - это байты.

Чтобы сохранить что-либо в компьютере, вы должны сначала закодировать это, то есть преобразовать в байты. Например:


  • Если вы хотите сохранить музыку, вы должны сначала закодировать ее, используя MP3, WAV и т.д.

  • Если вы хотите сохранить изображение, вы должны сначала закодировать его, используя PNG, JPEG и т.д.

  • Если вы хотите сохранить текст, вы должны сначала закодировать его, используя ASCII, UTF-8 и т.д.

MP3, WAV, PNG, JPEG, ASCII и UTF-8 являются примерами кодировок. Кодировка - это формат для представления аудио, изображений, текста и т.д. В байтах.

В Python строка байтов - это просто последовательность байтов. Она недоступна для чтения человеком. По сути, все должно быть преобразовано в строку байтов, прежде чем его можно будет сохранить в компьютере.

С другой стороны, символьная строка, часто называемая просто "строкой", представляет собой последовательность символов. Она удобочитаема для человека. Символьная строка не может быть сохранена непосредственно в компьютере, она должна быть сначала закодирована (преобразована в строку байтов). Существует несколько кодировок, с помощью которых символьная строка может быть преобразована в строку байтов, таких как ASCII и UTF-8.

'I am a string'.encode('ASCII')

Приведенный выше код Python будет кодировать строку 'I am a string' с использованием кодировки ASCII. Результатом приведенного выше кода будет строка в байтах. Если вы напечатаете это, Python представит это как b'I am a string'. Помните, однако, что строки байтов не читаются человеком, просто Python декодирует их из ASCII при печати. В Python строка байтов представлена символом b, за которым следует представление строки байтов в формате ASCII.

Строка байтов может быть декодирована обратно в символьную строку, если вы знаете кодировку, которая использовалась для ее кодирования.

b'I am a string'.decode('ASCII')

Приведенный выше код вернет исходную строку 'I am a string'.

Кодирование и декодирование - это обратные операции. Все должно быть закодировано, прежде чем его можно будет записать на диск, и оно должно быть декодировано, прежде чем его сможет прочитать человек.

Ответ 2

Предполагая, что Python 3 (в Python 2 это различие немного менее четко определено) - строка представляет собой последовательность символов, т.Е. кодовые точки unicode; это абстрактное понятие, и его нельзя сохранить непосредственно на диске. Строка байтов - это последовательность, что неудивительно, байтов - вещей, которые могут храниться на диске. Сопоставление между ними - это кодировка - их довольно много (и возможно бесконечно много) - и вам нужно знать, что применимо в конкретном случае, чтобы выполнить преобразование, поскольку другая кодировка может сопоставить одни и те же байты с другой строкой:

>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-16')
'蓏콯캁澽苏'
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-8')
'τoρνoς'

Как только вы узнаете, какую из них использовать, вы можете использовать .decode() метод строки байтов, чтобы получить из нее нужную строку символов, как описано выше. Для полноты картины, .encode() метод символьной строки работает противоположным образом:

>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'
Ответ 3

Примечание: Я подробнее остановлюсь на своем ответе для Python 3, поскольку срок службы Python 2 очень близок.

В Python 3

bytes состоит из последовательностей 8-битных значений без знака, в то время как str состоит из последовательностей кодовых точек Unicode, которые представляют текстовые символы человеческих языков.

>>> # bytes
>>> b = b'h\x65llo'
>>> type(b)
<class 'bytes'>
>>> list(b)
[104, 101, 108, 108, 111]
>>> print(b)
b'hello'
>>>
>>> # str
>>> s = 'nai\u0308ve'
>>> type(s)
<class 'str'>
>>> list(s)
['n', 'a', 'i', '̈', 'v', 'e']
>>> print(s)
naïve

Несмотря на то, что bytes и str, похоже, работают одинаково, их экземпляры несовместимы друг с другом, т. е. экземпляры bytes и str > нельзя использовать вместе с операторами, подобными + и,,,. Кроме того, имейте в виду, что сравнение bytes и str экземпляров на равенство, т. Е. использование ==, всегда будет равно False даже если они содержат точно такие же символы.

>>> # concatenation
>>> b'hi' + b'bye' # this is possible
b'hibye'
>>> 'hi' + 'bye' # this is also possible
'hibye'
>>> b'hi' + 'bye' # this will fail
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> '
hi' + b'bye' # this will also fail
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>>
>>> # comparison
>>> b'
red' > b'blue' # this is possible
True
>>> '
red'> 'blue' # this is also possible
True
>>> b'
red' > 'blue' # you can't compare bytes with str
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'bytes' and 'str'
>>> 'red' > b'blue' # you can't compare str with bytes
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'bytes'
>>> b'blue' == 'red' # equality between str and bytes always evaluates to False
False
>>> b'blue' == 'blue' # equality between str and bytes always evaluates to False
False

Еще одна проблема при работе с bytes и str присутствует при работе с файлами, которые возвращаются с помощью open встроенной функции. С одной стороны, если вы хотите прочитать или записать двоичные данные в файл / из файла, всегда открывайте файл, используя двоичный режим, такой как 'rb' или 'wb'. С другой стороны, если вы хотите прочитать или записать данные в Юникоде в файл / из файла, помните о кодировке вашего компьютера по умолчанию, поэтому при необходимости передайте параметр encoding, чтобы избежать неожиданностей.

В Python 2

str состоит из последовательностей 8-битных значений, в то время как unicode состоит из последовательностей символов Unicode. Следует иметь в виду, что str и unicode можно использовать вместе с операторами, если str состоит только из 7-битных символов ASCI.

Может быть полезно использовать вспомогательные функции для преобразования между str и unicode в Python 2 и между bytes и str в Python 3.

Ответ 4

Давайте возьмем простую односимвольную строку 'š' и закодируем ее в последовательность байтов:

>>> 'š'.encode('utf-8')
b'\xc5\xa1'

Для целей этого примера давайте отобразим последовательность байтов в ее двоичной форме:

>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'

Теперь вообще невозможно декодировать информацию обратно, не зная, как она была закодирована. Только если вы знаете, что использовалась текстовая кодировка UTF-8, вы можете следовать алгоритму декодирования UTF-8 и получить исходную строку:

11000101 10100001
^^^^^ ^^^^^^
00101 100001

Вы можете отобразить двоичное число 101100001 обратно в виде строки:

>>> chr(int('101100001', 2))
'š'
python string