TL;博士
struct.pack('<QBBHHL', *uuid_foo.fields[::-1])
介绍
尽管 Cat++ 的答案非常棒,但它会将 UUID 分成两半以将其放入两个无符号长整数中。我想打包每个字段,这给我留下了以下内容:
def maxsize(size: typing.Union[int,str]):
""" Useful for playing with different struct.pack formats """
if isinstance(size, str):
size = struct.calcsize(size)
return 2 ** (4 * size) - 1
uuid_max = uuid.UUID('ffffffff-ffff-ffff-ffff-ffffffffffff')
tuple(maxsize(len(f)) for f in str(u).split('-'))
# (4294967295, 65535, 65535, 65535, 281474976710655)
uuid_max.fields
# (4294967295, 65535, 65535, 255, 255, 281474976710655)
uuid_foo = UUID('909822be-c5c4-432f-95db-da1be79cf067')
uuid_foo.fields
# (2425889470, 50628, 17199, 149, 219, 239813384794215)
前五个字段很容易,因为它们已经排列为无符号 8、4、4、2、2 大小的整数。最后一个需要另一个答案的一些额外帮助。
注意:填充只会在连续的结构成员之间自动添加。在编码结构的开头或结尾处不添加任何填充。
使用非本机大小和对齐方式时不添加填充,例如使用“<”、“>”、“=”和“!”。
要将结构的结尾与特定类型的对齐要求对齐,请以该类型的代码结束格式,并且重复计数为零。请参阅示例。
struct.pack('>LHHBBQ', *uuid_foo.fields)
# b'\x90\x98"\xbe\xc5\xc4C/\x95\xdb\x00\x00\xda\x1b\xe7\x9c\xf0g'
# ^^ ^^ these empty bytes won't work!
实际答案
由于最后一个字段的大小为 12,因此您必须将其打包并向后解包,小端。这将在最后留下零,而不是在第五和第六字段之间。
struct.unpack('<QBBHHL', struct.pack('<QBBHHL', *uuid_foo.fields[::-1]))
# (281474976710655, 255, 255, 65535, 65535, 4294967295)
uuid_foo.fields
# (4294967295, 65535, 65535, 255, 255, 281474976710655)
重新生成它需要您再反转一次。
uuid_packed = struct.pack('<QBBHHL', *uuid_foo.fields[::-1])
uuid_unpacked = struct.unpack('<QBBHHL', uuid_packed)[::-1]
uuid.UUID(fields=uuid_unpacked)
# UUID('909822be-c5c4-432f-95db-da1be79cf067')