Как я могу преобразовать строку байтов в int в Python?
Скажи так: 'y\xcc\xa6\xbb'
Я придумал умный / глупый способ сделать это:
sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))
Я знаю, что должно быть что-то встроенное или в стандартной библиотеке, которая делает это проще ...
Это отличается от преобразования строки шестнадцатеричных цифр, для которой вы можете использовать int (xxx, 16), но вместо этого я хочу преобразовать строку фактических значений байтов.
ОБНОВИТЬ:
Мне нравится ответ Джеймса немного лучше, потому что он не требует импорта другого модуля, но метод Грега быстрее:
>>> from timeit import Timer
>>> Timer('struct.unpack("<L", "y\xcc\xa6\xbb")[0]', 'import struct').timeit()
0.36242198944091797
>>> Timer("int('y\xcc\xa6\xbb'.encode('hex'), 16)").timeit()
1.1432669162750244
Мой хакерский метод:
>>> Timer("sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))").timeit()
2.8819329738616943
ДОПОЛНИТЕЛЬНОЕ ОБНОВЛЕНИЕ:
Кто-то спросил в комментариях, в чем проблема с импортом другого модуля. Что ж, импорт модуля не обязательно дешев, посмотрите:
>>> Timer("""import struct\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""").timeit()
0.98822188377380371
В том числе стоимость импорта модуля сводит на нет практически все преимущества этого метода. Я полагаю, что это будет включать только затраты на его импорт один раз для всего теста; посмотрите, что происходит, когда я заставляю его каждый раз перезагружаться
>>> Timer("""reload(struct)\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""", 'import struct').timeit()
68.474128007888794
Излишне говорить, что если вы выполняете много операций этого метода для одного импорта, это становится пропорционально меньшей проблемой. Это также, вероятно, стоимость ввода-вывода, а не процессора, поэтому она может зависеть от производительности и характеристик нагрузки конкретной машины.
int.from_bytes
) не выполняетсяstruct.unpack
на моем компьютере. Рядом с более читабельным ИМО.Ответы:
Вы также можете использовать модуль struct для этого:
источник
В Python 3.2 и позже используйте
или
в соответствии с порядком байтов вашей строки.
Это также работает для целых чисел bytestring произвольной длины и для целых чисел со знаком с двумя дополнительными числами путем указания
signed=True
. Смотрите документы дляfrom_bytes
.источник
os.urandom(4)
байтов ** 1,4 мкс ** (структура) против ** 2,3 мкс ** (int.from_bytes) в моем процессоре. питон 3.5.2Как сказал Грег, вы можете использовать struct, если вы имеете дело с двоичными значениями, но если у вас просто есть «шестнадцатеричное число», но в байтовом формате, вы можете просто преобразовать его следующим образом:
... это так же, как:
... за исключением того, что он будет работать для любого количества байтов.
источник
int(''.join(reversed(s)).encode('hex'), 16)
Я использую следующую функцию для преобразования данных между int, hex и байтами.
Источник: http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html
источник
Предупреждение: вышесказанное строго зависит от платформы. И спецификатор "I", и порядковый номер преобразования string-> int зависят от конкретной реализации Python. Но если вы хотите преобразовать много целых чисел / строк одновременно, то модуль массива сделает это быстро.
источник
В Python 2.x вы могли использовать спецификаторы формата
<B
для байтов без знака и<b
для байтов со знаком сstruct.unpack
/struct.pack
.Например:
Let
x
='\xff\x10\x11'
И:
Это
*
требуется!Видеть https://docs.python.org/2/library/struct.html#format-characters для получения списка спецификаторов формата.
источник
Тест 1: обратный:
Тест 2: Количество байтов> 8:
Тест 3: увеличение на единицу:
Тест 4: добавьте один байт, скажите «A»:
Тест 5: разделить на 256:
Результат равен результат теста 4, как и ожидалось.
источник
Я изо всех сил пытался найти решение для последовательности байтов произвольной длины, которая работала бы в Python 2.x. Наконец, я написал этот, он немного хакерский, потому что он выполняет преобразование строк, но он работает.
Функция для Python 2.x, произвольной длины
Эта функция имеет два требования:
Вход
data
должен бытьbytearray
. Вы можете вызвать функцию следующим образом:Данные должны быть порядковыми. Если у вас есть значение с прямым порядком байтов, вы должны сначала изменить его:
Конечно, это следует использовать, только если необходима произвольная длина. В противном случае придерживайтесь более стандартных способов (например
struct
).источник
int.from_bytes - лучшее решение, если вы используете версию> = 3.2. Решение "struct.unpack" требует строку, поэтому оно не будет применяться к массивам байтов. Вот еще одно решение:
hex (bytes2int ([0x87, 0x65, 0x43, 0x21])) возвращает «0x87654321».
Он обрабатывает большие и меньшие числа байтов и легко модифицируется для 8 байтов
источник
Как уже упоминалось выше, использование
unpack
функции struct является хорошим способом. Если вы хотите реализовать свою собственную функцию, есть другое решение:источник
В Python 3 вы можете легко преобразовать байтовую строку в список целых чисел (0..255) с помощью
источник
Достаточно быстрый метод, использующий array.array, который я использовал в течение некоторого времени:
предопределенные переменные:
к int: (читать)
из int: (написать)
Возможно, они могут быть быстрее, хотя.
РЕДАКТИРОВАТЬ:
Для некоторых чисел, вот тест производительности (Anaconda 2.3.0), показывающий стабильные средние значения при чтении по сравнению с
reduce()
:Это необработанный тест производительности, так что endian pow-flip исключен. Функции показано , применяется один и тот же сдвиг-ORing операцию как для цикла, и это просто , как это имеет быстрый итеративный производительность рядом .
shift
arr
array.array('B',[0,0,255,0])
dict
Я должен также отметить, что эффективность измеряется с точностью до среднего времени.
источник