Распаковать символы формата в Python - PullRequest
4 голосов
/ 07 февраля 2012

Мне нужен аналог Python для этой строки Perl:

unpack("nNccH*", string_val)

Мне нужен формат данных nNccH* - в символах формата Python.

В Perl он распаковывает двоичные данные в пятьпеременные:

  • 16-битное значение в «сети» (с прямым порядком байтов)
  • 32-битное значение в «сети» (с прямым порядком байтов)
  • Знаковый символ (8-разрядное целое число) значение
  • Значение знакового символа (8-разрядное целое число)
  • Шестнадцатеричная строка, сначала большой полубайт

Но я не могу сделать это вPython

Подробнее:

bstring = ''
while DataByte = client[0].recv(1):
    bstring += DataByte
print len(bstring)
if len(bstring):
    a, b, c, d, e = unpack("nNccH*", bstring)

Я никогда не писал на Perl или Python, но моя текущая задача - написать многопоточный сервер Python, написанный на Perl ...

Ответы [ 2 ]

7 голосов
/ 07 февраля 2012

Формат Perl "nNcc" эквивалентен формату Python "!HLbb". В Python нет прямого эквивалента для Perl "H*".

Есть две проблемы.

  • Python's struct.unpack не принимает подстановочный знак, *
  • Python struct.unpack не "шестнадцатеричный" строки данных

Первая проблема может быть решена с помощью вспомогательной функции, такой как unpack.

Вторую проблему можно решить с помощью binascii.hexlify:

import struct
import binascii

def unpack(fmt, data):
    """
    Return struct.unpack(fmt, data) with the optional single * in fmt replaced with
    the appropriate number, given the length of data.
    """
    # http://stackoverflow.com/a/7867892/190597
    try:
        return struct.unpack(fmt, data)
    except struct.error:
        flen = struct.calcsize(fmt.replace('*', ''))
        alen = len(data)
        idx = fmt.find('*')
        before_char = fmt[idx-1]
        n = (alen-flen)//struct.calcsize(before_char)+1
        fmt = ''.join((fmt[:idx-1], str(n), before_char, fmt[idx+1:]))
        return struct.unpack(fmt, data)

data = open('data').read()
x = list(unpack("!HLbbs*", data))
# x[-1].encode('hex') works in Python 2, but not in Python 3
x[-1] = binascii.hexlify(x[-1])
print(x)

При проверке данных, полученных с помощью этого сценария Perl:

$line = pack("nNccH*", 1, 2, 10, 4, '1fba');
print "$line";

Скрипт Python дает

[1, 2, 10, 4, '1fba']
6 голосов
/ 07 февраля 2012

Эквивалентная функция Python, которую вы ищете - struct.unpack.Документация строки формата находится здесь: http://docs.python.org/library/struct.html

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

...