如何将UUID打包到Python中的结构中?

时间:2011-07-29 18:00:04

标签: python struct uuid pack

我有一个UUID,我正在考虑使用UUID.int打包到一个结构中,它将它变成一个128位整数。但是没有一个struct format字符足以存储它,如何去做呢?

示例代码:

s = struct.Struct('L')
unique_id = uuid.uuid4()    
tuple = (unique_id.int)
packed = s.pack(*tuple)

问题是,结构格式'L'只有4个字节...我需要存储16.将它存储为32字符串有点多。

3 个答案:

答案 0 :(得分:12)

这是一个128位整数,你期望它变成什么?您可以将其拆分为多个组件 - 例如两个64位整数:

max_int64 = 0xFFFFFFFFFFFFFFFF
packed    = struct.pack('>QQ', (u.int >> 64) & max_int64, u.int & max_int64)
# unpack
a, b     = struct.unpack('>QQ', packed)
unpacked = (a << 64) | b

assert u.int == unpacked

答案 1 :(得分:7)

当您使用uuid模块时,您可以简单地使用bytes成员,该成员将 UUID保存为16字节字符串(包含以big-endian字节顺序排列的六个整数字段) )

u = uuid.uuid4()
packed = u.bytes # packed is a string of size 16
assert u == uuid.UUID(bytes=packed)

答案 2 :(得分:0)

TL; DR

struct.pack('<QBBHHL', *uuid_foo.fields[::-1])

简介

尽管Cat ++的回答确实很棒,但它会将UUID分成两半,以适合两个无符号长整型。我想要to pack each field,它给我留下了以下内容:

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个大小整数。最后一个必须为a little extra help from another answer

注意: 仅在连续的结构成员之间自动添加填充。在编码的结构的开头或结尾不会添加填充。

使用非本机大小和对齐方式(例如,与“ <”,“>”,“ =”和“!”一起使用。

要将结构的末尾与特定类型的对齐要求对齐,请使用重复类型为零的该类型的代码结束格式。请参见示例。

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')