python pack/unpack 数字指定字节数
python pack/unpack numbers specifyig number of bytes
我正在尝试将 Python 中的整数(>=0 && <2^32 当然)转换为 4 字节无符号整数表示并返回。
根据我对文档的理解,struct.pack
中给出的大小是标准大小,但不能保证大小。我怎样才能确保我得到 4 个字节?
我发现的一种使用 ctypes 的方法:
byte_repr=bytes(ctypes.c_uint32(data))
这是最pythonic的吗?返回的方式是什么(对于这个或任何其他解决方案)?
类型 int
和 bytes
具有您需要的方法。
请注意,我是从 class 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
>>>
考虑到上述间隔,您说的是 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
相关(远程):.
[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。
我正在尝试将 Python 中的整数(>=0 && <2^32 当然)转换为 4 字节无符号整数表示并返回。
根据我对文档的理解,struct.pack
中给出的大小是标准大小,但不能保证大小。我怎样才能确保我得到 4 个字节?
我发现的一种使用 ctypes 的方法:
byte_repr=bytes(ctypes.c_uint32(data))
这是最pythonic的吗?返回的方式是什么(对于这个或任何其他解决方案)?
类型 int
和 bytes
具有您需要的方法。
请注意,我是从 class 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
>>>
考虑到上述间隔,您说的是 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
相关(远程):
[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。