Python: Обработка структур, содержащих массивы, с помощью модуля struct - PullRequest
0 голосов
/ 31 августа 2018

Хотя модуль struct делает обработку C-подобных структур, содержащих скалярные значения, очень простой, я не вижу, как разумно обрабатывать структуры, содержащие массивы.

Например, если у меня есть следующая структура C:

struct my_struct {
    int a1[6];
    double a2[3];
    double d1;
    double d2;
    int i1;
    int i2;
    int a3[6];
    int i3;
};

и хотите распаковать его значения и использовать те же переменные (a1, a2, a3, d1, d2, i1, i2, i3) в Python, Я сталкиваюсь с проблемой, что struct просто дает мне каждое значение в кортеже индивидуально. Вся информация о том, какие значения должны быть сгруппированы в массив, теряется:

# doesn’t work!
a1, a2, d1, d2, i1, i2, a3, i3 = struct.unpack(
    '6i3dddii6ii', b'abcdefghijklmnopqrstuvwxy' * 4
)

Вместо этого я должен нарезать и разделить кортеж вручную, что является очень утомительной и подверженной ошибкам процедурой:

t = struct.unpack('6i3dddii6ii', b'abcdefghijklmnopqrstuvwxy' * 4)
a1 = t[:6]
a2 = t[6:9]
d1, d2, i1, i2 = t[9:13]
a3 = t[13:19]
i3 = t[19]

Есть ли лучший способ обработки массивов с помощью struct?

1 Ответ

0 голосов
/ 10 октября 2018

Вы можете использовать библиотеку конструкций , которая в значительной степени обертывает модуль struct и делает анализ и построение двоичных данных более удобным.

Вот базовый пример:

import construct

my_struct = construct.Struct(
    "a1" / construct.Array(6, construct.Int32sl),
    "a2" / construct.Array(3, construct.Float64l),
    "d1" / construct.Float64l,
    "d2" / construct.Float64l,
    "i1" / construct.Int32sl,
    "i2" / construct.Int32sl,
    "a3" / construct.Array(6, construct.Int32sl),
    "i3" / construct.Int32sl
)



parsed_result = my_struct.parse(b'abcdefghijklmnopqrstuvwxy' * 4)

# now all struct attributes are available
print(parsed_result.a1)
print(parsed_result.a2)
print(parsed_result.i3)


assert 'a1' in parsed_result
assert 'i3' in parsed_result
...