Как преобразовать байты в строку на Pythonх 2 и 3

  1. Преобразование байт в строку на Python 2.x
  2. Преобразование байт в строку на Python 3.x
  3. Сравнение производительности и вывод различных методов преобразования байт в строку

В этой обучающей статье будет рассказано, как преобразовать байты в строки на Python 2.x и Python 3.x.

Преобразование байт в строку на Python 2.x

Байты на Python 2.7 идентичны str, поэтому переменная, инициализированная как bytes, по своей сути является строкой.

Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> A = b'cd'
>>> A
'cd'
>>> type(A)
<type 'str'>

Преобразование байт в строку на Python 3.x

bytes - это новый тип данных, введённый на Python 3.

Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> A = b'cd'
>>> A
b'cd'
>>> type(A)
<class 'bytes'>
>>> 

Тип элементов данных в байтах - int.

>>> A = b'cd'
>>> A[0]
99
>>> type(A[0])
<class 'int'>

Конвертируйте байты в строки с помощью decode на Python 3.x

Метод .decodebytesможет преобразовывать байты в строку с помощью заданного методаencoding. В большинстве случаев это нормально, если вы оставите методencodingпо умолчаниюutf-8, но это не всегда безопасно, так как байты могут быть закодированы другими методами кодирования, а неutf-8`.

>>> b'\x50\x51'.decode()
'PQ'
>>> b'\x50\x51'.decode('utf-8')
'PQ'
>>> b'\x50\x51'.decode(encoding = 'utf-8')
'PQ'

Три способа декодирования bytes, как показано выше, идентичны, потому что в качестве метода кодирования используется utf-8.

Это может привести к возникновению ошибок при использовании utf-8, но байты при этом не кодируются.

>>> b'\x50\x51\xffed'.decode('utf-8')
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    b'\x50\x51\xffed'.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 2: invalid start byte

Мы получаем UnicodeDecodeError, который говорит, что utf-8 - неправильный кодек.

У нас есть два подхода к решению этой проблемы кодирования.

backslashreplace, ignore или replace в качестве параметров к errors

decode имеет другой параметр, кроме encoding - errors. Он определяет поведение, когда происходит ужас. Значение по умолчанию errors - strict, что означает, что он вызывает ошибку, если ошибка происходит в процессе декодирования.

У error есть другие опции, такие как ignore, replace или другие зарегистрированные codecs.register_error имена, backslashreplace, например.

ignore игнорирует ошибки декодирования и создает выходную строку так, как это возможно.

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

>>> b'\x50\x51\xffed'.decode('utf-8', 'backslashreplace')
'PQ\\xffed'
>>> b'\x50\x51\xffed'.decode('utf-8', 'ignore')
'PQed'
>>> b'\x50\x51\xffed'.decode('utf-8', 'replace')
'PQ�ed'

MS-DOS cp437 кодировка может быть использована, если кодировка данных байт неизвестна.

>>> b'\x50\x51\xffed'.decode('cp437')
'PQ\xa0ed'

chr для преобразования байт в строку на Python 3.x

chr(i, /) возвращает строку Unicode, состоящую из одного символа с порядковым номером. Это может преобразовать элемент bytes в строку, но не в полный bytes.

Мы могли бы использовать понимание списка или map для получения преобразованной строки из bytes при использовании chr для отдельного элемента.

>>> A =  b'\x50\x51\x52\x53'
>>> "".join([chr(_) for _ in A])
'PQRS'
>>> "".join(map(chr, A))
'PQRS'

Сравнение производительности и вывод различных методов преобразования байт в строку

Мы используем timeit для сравнения производительности методов, введенных в этом учебнике - decode и chr.

>>> import timeit
>>> timeit.timeit('b"\x50\x51\x52\x53".decode()', number=1000000)
0.1356779
>>> timeit.timeit('"".join(map(chr, b"\x50\x51\x52\x53"))', number=1000000)
0.8295201999999975
>>> timeit.timeit('"".join([chr(_) for _ in b"\x50\x51\x52\x53"])', number=1000000)
0.9530071000000362

Из показанного выше времени выполнения видно, что decode() гораздо быстрее и chr() относительно неэффективна, так как ей нужно восстанавливать строку из одного символа строки.

Мы рекомендуем использовать decode в критичном для производительности приложении.

Сопутствующая статья - Python Bytes

  • Как конвертировать байты в интегралы на Python 2.7 и 3.x
  • Как преобразовать Int в байты на Pythonх 2 и 3
  • Как преобразовать строку в байты на Python
  • Сопутствующая статья - Python Encoding-Decoding

  • Как конвертировать байты в интегралы на Python 2.7 и 3.x
  • Как преобразовать Int в байты на Pythonх 2 и 3
  • Как преобразовать строку в байты на Python
  • comments powered by Disqus