【问题标题】:Why can't Python struct module pack (or unpack) multi bytes with little endian为什么 Python struct module 不能用 little endian 打包(或解包)多字节
【发布时间】:2019-07-22 12:57:53
【问题描述】:

我正在处理一些多字节问题。例如,我有一个变量a = b'\x00\x01\x02\x03',它是一个bytes 对象而不是int。我想struct.pack 它用little endian 组成一个包,但是<4s 不起作用。事实上,<4s>4s 得到相同的结果。如果我希望结果为b'\x03\x02\x01\x00,该怎么办。
我知道我可以使用struct.pack('<L', struct.unpack('>L', a)),但它是处理多字节对象的唯一正确方式吗?

例子:

import struct
import secrets

mhdr = b'\x20'
joineui = b'\x00\x01\x02\x03\x04\x05\x06\x07'
deveui = b'\x08\x09\x10\x11\x12\x13\x14\x15'
devnonce = secrets.token_bytes(2)

joinreq = struct.pack(
    '<s8s8s2s',
    mhdr,
    joineui,
    deveui,
    devnonce,
)

# The expected joinreq should be b'\x20\x07\x06\x05\x04\x03\x02\x01\x00\x15\x14\x13\x12\x11\x10\x09\x08...'

【问题讨论】:

  • 4s 表示四个单独的字节。 Endiannes 仅适用于多字节值,因此不会影响您读取字符串的方式。
  • @jdehesa 不,4s 表示一个 bytes 4 字节长度的对象,而不是四个单独的字节。
  • 是的,但我的意思是“对象”由四个单独的字节组成。如果您有4i,它将是四个单独的整数,您可以更改每个整数的字节顺序,但第一个整数始终是第一个,然后是第二个,依此类推。对于您的情况,您可能只是反转字节字符串,因为每个上只有一个“对象”(joineui[::-1]deveui[::-1])。
  • @jdehesa 这行得通,但我需要在程序的几个部分中反转它们,我还需要从服务器返回unpack 数据,我必须在多个服务器上执行这些[::-1]字节字段。这感觉很糟糕。

标签: python struct byte endianness pack


【解决方案1】:

在我看来,您不希望有 4 个单个字符,而是希望有 1 个整数。 因此,您应该尝试使用 'i' 或 'I' 而不是 '4s'(无论是签名还是未签名)。

你的例子应该是这样的

import struct
import secrets

mhdr = b'\x20'
joineui = b'\x00\x01\x02\x03\x04\x05\x06\x07'
deveui = b'\x08\x09\x10\x11\x12\x13\x14\x15'
devnonce = secrets.token_bytes(2)

joinreq = struct.pack(
    '<BQQH', #use small letters if the values are signed instead of unsigned
    mhdr,
    joineui,
    deveui,
    devnonce,
)

“Q”代表long long unsigned (8byte)。如果你想使用浮点数,你可以使用 d 双浮点精度(8 字节)。

你可以看到the documentation of struct中所有字母的含义。

【讨论】:

  • 不能直接工作,因为如果我使用QQHB,下面的参数必须是四个整数而不是四个bytes。所以我必须首先将所有 bytes 对象解压缩为整数,正如我在问题中所解释的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2012-10-09
  • 1970-01-01
  • 2010-10-16
相关资源
最近更新 更多