【问题标题】:python pack/unpack numbers specifyig number of bytespython打包/解包数字指定字节数
【发布时间】:2020-07-17 15:18:25
【问题描述】:

我正在尝试将 Python 中的 int 数字(当然是 >=0 &&

据我了解,struct.pack 中给出的尺寸是标准尺寸,但不能保证尺寸。如何确保我得到 4 个字节?

我发现使用 ctypes 的一种方法:

byte_repr=bytes(ctypes.c_uint32(data))

这是最蟒蛇的吗?以及返回的方法是什么(对于这个或任何其他解决方案)?

【问题讨论】:

  • 除非您正在序列化对象,否则如果您关心 Python 中有多少字节,那么您已经将“pythonic”抛到了窗外。
  • @user10987432 嗯,这不是真的。例如,如果他通过网络以指定的大小发送一些东西,那不是“......把pythonic扔到窗外”
  • @maor10 如果您通过网络发送某些内容,则根据定义,这就是“序列化对象”。
  • 好吧,python 中的任何东西都是“对象”,所以这有点争议。他专门询问了一个数字——将数字转换为二进制表示并不是“unpythonic”,这样说有点荒谬
  • 大小不保证”是什么意思(对于struct)?

标签: python struct ctypes


【解决方案1】:

intbytes 类型具有您需要的方法。

请注意,我是从 int 类调用 from_bytes,但它可以从 int 实例对象调用:

>>> a = 2**32-1
>>> a.to_bytes(4, 'little')
b'\xff\xff\xff\xff'
>>> b = a.to_bytes(4, 'little')
>>> c = int.from_bytes(b, 'little')
>>> c
4294967295
>>> a
4294967295
>>>

【讨论】:

    【解决方案2】:

    鉴于提到的间隔,您说的是 unsigned ints
    [Python 3.Docs]: struct - Interpret strings as packed binary data 工作正常(嗯,在 sizeof(int) == 4 的平台(编译器)上)。
    因为对于绝大多数环境,上述情况都是正确的,所以您可以安全地使用它(除非您确定代码将在一个奇异的平台上运行,编译器用于构建 Python不同)。

    >>> import struct
    >>>
    >>> bo = "<"  # byte order: little endian
    >>>
    >>> ui_max = 0xFFFFFFFF
    >>>
    >>> ui_max
    4294967295
    >>> buf = struct.pack(bo + "I", ui_max)
    >>> buf, len(buf)
    (b'\xff\xff\xff\xff', 4)
    >>>
    >>> ui0 = struct.unpack(bo + "I", buf)[0]
    >>> ui0
    4294967295
    >>>
    >>> i0 = struct.unpack(bo + "i", buf)[0]  # signed int
    >>> i0
    -1
    >>> struct.pack(bo + "I", 0)
    b'\x00\x00\x00\x00'
    >>>
    >>> struct.pack(bo + "I", ui_max + 1)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    struct.error: argument out of range
    >>>
    >>> struct.unpack(bo + "I", b"1234")
    (875770417,)
    >>>
    >>> struct.unpack(bo + "I", b"123")  # 3 bytes buffer
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    struct.error: unpack requires a buffer of 4 bytes
    >>>
    >>> struct.unpack(bo + "I", b"12345")  # 5 bytes buffer
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    struct.error: unpack requires a buffer of 4 bytes
    

    相关(远程):[SO]: Maximum and minimum value of C types integers from Python

    [Python 3.Docs]: ctypes - A foreign function library for Python变种:

    >>> # Continuation of previous snippet
    >>> import ctypes as ct
    >>>
    >>> ct_ui_max = ct.c_uint32(ui_max)
    >>>
    >>> ct_ui_max
    c_ulong(4294967295)
    >>>
    >>> buf = bytes(ct_ui_max)
    >>> buf, len(buf)
    (b'\xff\xff\xff\xff', 4)
    >>>
    >>> ct.c_uint32(ui_max + 1)
    c_ulong(0)
    >>>
    >>> ct.c_uint32.from_buffer_copy(buf)
    c_ulong(4294967295)
    >>> ct.c_uint32.from_buffer_copy(buf + b"\x00")
    c_ulong(4294967295)
    >>> ct.c_uint32.from_buffer_copy(b"\x00" + buf)  # 0xFFFFFF00 (little endian)
    c_ulong(4294967040)
    >>>
    >>> ct.c_uint32.from_buffer_copy(buf[:-1])
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: Buffer size too small (3 instead of at least 4 bytes)
    

    注意:@progmatico 的回答更简单直接,因为它不涉及除 builtin ([Python 3.Docs]: Built-in Types - Additional Methods on Integer Types) 以外的任何模块。作为旁注,可以使用 sys.byteorder

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-28
      • 2017-12-26
      • 1970-01-01
      • 2017-05-30
      • 2019-04-14
      • 1970-01-01
      相关资源
      最近更新 更多