Python 模块 UUID 学习使用

Python 模块 UUID 学习使用

一、UUID介绍

UUID: 通用唯一标识符 ( Universally Unique Identifier ), 对于所有的UUID它可以保证在空间和时间上的唯一性. 它是通过MAC地址, 时间戳, 命名空间, 随机数, 伪随机数来保证生成ID的唯一性, 有着固定的大小( 128 bit ). 它的唯一性和一致性特点使得可以无需注册过程就能够产生一个新的UUID. UUID可以被用作多种用途, 既可以用来短时间内标记一个对象, 也可以可靠的辨别网络中的持久性对象.

为什么要使用UUID?

很多应用场景需要一个id, 但是又不要求这个id 有具体的意义, 仅仅用来标识一个对象. 常见的例子有数据库表的id 字段. 另一个例子是前端的各种UI库, 因为它们通常需要动态创建各种UI元素, 这些元素需要唯一的id , 这时候就需要使用UUID了.

二、Python uuid模块介绍

python的uuid模块提供UUID类和函数uuid1(), uuid3(), uuid4(), uuid5() 来生成1, 3, 4, 5各个版本的UUID ( 需要注意的是: python中没有uuid2()这个函数). 用uuid1()或uuid4()可以获得一个唯一的ID,uuid1()包含了主机的网络名称,uuid4()不涉及网络主机名,仅生成一个随机UUID,因此从隐私保护角度uuid4()更加安全。对uuid模块中最常用的几个函数总结如下:

2.1、uuid.uuid1([node[, clock_seq]]) : 基于时间戳

使用主机ID, 序列号, 和当前时间来生成UUID, 可保证全球范围的唯一性. 但由于使用该方法生成的UUID中包含有主机的网络地址, 因此可能危及隐私. 该函数有两个参数, 如果 node 参数未指定, 系统将会自动调用 getnode() 函数来获取主机的硬件地址. 如果 clock_seq 参数未指定系统会使用一个随机产生的14位序列号来代替.

2.2、uuid.uuid3(namespace, name) : 基于名字的MD5散列值

通过计算命名空间和名字的MD5散列值来生成UUID, 可以保证同一命名空间中不同名字的唯一性和不同命名空间的唯一性, 但同一命名空间的同一名字生成的UUID相同.

2.3、uuid.uuid4() : 基于随机数

通过随机数来生成UUID. 使用的是伪随机数有一定的重复概率.

2.4、uuid.uuid5(namespace, name) : 基于名字的SHA-1散列值

通过计算命名空间和名字的SHA-1散列值来生成UUID, 算法与 uuid.uuid3() 相同.

三、python 中uuid 方法介绍

3.1、uuid.UUID 类

class uuid.UUID([hex[, bytes[, bytes_le[, fields[, int[, version]]]]]]) 

  该类用于从参数给定的内容中实例化UUID对象(hex, bytes, bytes_le, fields, int 必须且只能指定一个):

  hex:指定32个字符以创建UUID对象,当指定一个32个字符构成的字符串来创建一个UUID对象时,花括号、连字符和URN前缀等都是可选的;

  bytes:指定一个大端字节序的总长16字节的字节串来创建UUID对象;

  bytes_le:指定一个小端字节序的总长16字节的字节串来创建UUID对象;

  fields:指定6个整数域,共计128位来创建UUID(其中,32位作为time_low段,16位作为time_mid段,16位作为time_hi_version段,8位作为clock_seq_hi_variant段,8位作为clock_seq_low段,48位作为node段);

  int:直接指定一个长度为128个二进制位的整数用于创建UUID对象;

  version:(可选)指定UUID的版本,从15,一旦指定了该参数,生成的UUID将具有自己的变体(variant)和版本数,具体请参考 RFC 4122

3.2、uuid对象属性

3.2.1、UUID.bytes

以16个字节构成的字节串形式表示UUID,包含6个大端字节序的整数域;

>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
>>> b.bytes
'M\xfck\x14r\x133c\x80\t\xb2<V\xe3\xa1\xb1'
3.2.2、UUID.bytes_le

以16个字节构成的字节串形式表示UUID,包含6个小端字节序的整数域;

>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
>>> b.bytes_le
'\x14k\xfcM\x13rc3\x80\t\xb2<V\xe3\xa1\xb1'

字节序相关:https://blog.csdn.net/damanchen/article/details/112424874

3.2.3、UUID.fields

以元组形式存放的UUID的6个整数域,该元组中的6个元素分别可以通过6个属性查看,还额外导出了两个属性(下面的每个域的名称也是UUID对象的一个属性):

在这里插入图片描述

[time-low]-[time-mide]-[time-high-and-version]-[clock-seq-and-reserved 和 clock-seq-low]-[node]

time-low = 32位 unsigned integer
time-mid = 16位 unsigned integer
time-high-and-version = 16位 unsigned integer(时间戳高位部分与版本(Version)号混合)
clock-seq-and-reserved = 8位 unsigned integer(时钟序列高位部分与预定义变量(Variant)混合组成)
clock-seq-low = 8位 unsigned integer
node = 48位 unsigned integer
含义
time_lowUUID的初始32位
time_mid接前一域的16位
time_hi_version接前一域的16位
clock_seq_hi_variant接前一域的8位
clock_seq_low接前一域的8位
nodeUUID的最后48位
timeUUID的总长60位的时间戳
clock_seq14位的序列号
>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
>>> b.fields
(1308388116L, 29203L, 13155L, 128L, 9L, 195972225540529L)
3.2.4、UUID.hex

以32个字符表示的UUID

>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
>>> b.hex
'4dfc6b14721333638009b23c56e3a1b1'

3.2.5、UUID.int

以一个长度为128个二进制位的整数表示的UUID;

>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
>>> b.int
103661186321484643176355349665283285425L
3.2.6、UUID.urn

RFC 4122 中指定的URN形式表示的UUID

>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
>>> b.urn
'urn:uuid:4dfc6b14-7213-3363-8009-b23c56e3a1b1'
3.2.7、UUID.variant

UUID变体(variant),决定UUID内部的布局,已有的值为 RESERVED_NCS、``RFC_4122、``RESERVED_MICROSOFT RESERVED_FUTURE

变量(variant), 或称做类型, 4 bytes, 包括以下4种(其中X为任意值):

0XX NCS兼容预留
10X RFC4122采用
110 微软兼容预留
111 还未定义, 留作以后它用
>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
>>> b.variant
'specified in RFC 4122'
3.2.8、UUID.version

UUID版本,只有当变体为 RFC_4122 时才有效。

0001 时间的版本
0010 DCE Security
0011 MD5哈希
0100 ()随机数
0101 SHA-1哈希
>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
>>> b.version
3
3.2.9、uuid.getnode()

获取硬件的地址并以48位二进制长度的正整数形式返回,这里所说的硬件地址是指网络接口的MAC地址,如果一个机器有多个网络接口,可能返回其中的任一个。如果获取失败,将按照RFC 4122的规定将随机返回的48位二进制整数的第8位设置成1。

>>> import uuid
>>> b1 = uuid.getnode()
>>> b1
190070690681122
3.2.10、uuid.uuid1([node[, clock_seq]])

利用主机ID、序列号和当前时间生成一个UUID,如果参数 node 没有给定,会调用 getnode() 来获取硬件地址。如果参数中指定了 clock_seq ,使用参数中给定的时钟序列作为序列号,否则使用一个随机的14位长的序列号。

>>> import uuid
>>> b2 = uuid.uuid1()
>>> b2
UUID('326ee180-cf44-11ec-af81-acde48001122')
>>> b3 = uuid.uuid1(190070690681122)
>>> b3
UUID('f059ef8a-cf44-11ec-a1cd-acde48001122')

3.2.11、uuid.uuid3(namespace, name)

基于命名空间标识符(实质上是一个UUID)和一个名称(实质上是一个字符串)的MD5哈希值生成UUID。

>>> import uuid
>>> b = uuid.uuid3(uuid.NAMESPACE_DNS, "123")
>>> b
UUID('4dfc6b14-7213-3363-8009-b23c56e3a1b1')
3.2.12、uuid.uuid4()

生成一个随机的UUID

>>> import uuid
>>> c = uuid.uuid4()
>>> c
UUID('a46e5f4c-5945-496c-80d5-6a72ac11523b')
3.2.13、uuid.uuid5(namespace, name)

基于命名空间标识符(实质上是一个UUID)和一个名称(实质上是一个字符串)的SHA-1哈希值生成UUID

>>> import uuid
>>> d = uuid.uuid5(uuid.NAMESPACE_DNS, "123")
>>> d
UUID('37813542-0dca-5a8a-b2a2-b69c2d45583f')
3.2.14、uuid3()和uuid5()中提到的命名空间标识符,uuid模块定义了如下的备选项
uuid.NAMESPACE_DNS 
  当指定该命名空间时,参数 name 是一个完全限定的(fully-qualified)域名
  
uuid.NAMESPACE_URL 
  当指定该命名空间时,参数 name 是一个URL
  
uuid.NAMESPACE_OID 
  当指定该命名空间时,参数 name 是一个ISO OID
   
 uuid.NAMESPACE_X500 
		当指定该命名空间时,参数 name 是一个DER格式或文本格式的X.500 DN。
3.2.15、关于属性variant,uuid模块定义了如下的常量

uuid.RESERVED_NCS

该常量为兼容NCS而保留;0XX NCS兼容预留

>>> import uuid
>>> d1 = uuid.RESERVED_NCS
>>> d1
'reserved for NCS compatibility'

uuid.RFC_4122

按照 RFC 4122 的规定来确定UUID的布局;10X RFC4122采用

>>> import uuid
>>> d2 = uuid.RFC_4122 
>>> d2
'specified in RFC 4122'

uuid.RESERVED_MICROSOFT

该常量位兼容微软而保留;110 微软兼容预留

>>> import uuid
>>> d3 = uuid.RESERVED_MICROSOFT
>>> d3
'reserved for Microsoft compatibility'

uuid.RESERVED_FUTURE

该常量为未来可能的定义保留,111 还未定义, 留作以后它用

>>> import uuid
>>> d4 = uuid.RESERVED_FUTURE 
>>> d4
'reserved for future definition'
3.2.16、时间戳(timestamp), 60bit:

版本1: 时间戳采用UTC时间,以100ns为间隔,重1582年10月15日00:00:00.00开始计算

3.2.17、时钟序列, 14bit:

版本1: 用来防止在时间回调的情况下,导致的UUID重复问题
如果有时间回调(可能有系统断电导致),如果生成器在回调时间之后有生成新的UUID,那么时钟序列应该改变, 如果新生成的UUID时钟序列可知,那么时钟序列递增即可; 若不可知, 那么时钟序列应重置到一个47位随机数,或一个47位高质量的伪随机数,并且第48位设置为1,用来区别真正的MAC地址(由于所有MAC地址在网卡中第48为0)

3.2.18、节点(node), 48bit:

版本1: 为主机MAC地址, 若主机有多个MAC地址,随机选其中一个, 若系统没有MAC地址, 则采用(伪)随机数.

四、使用示例

4.1、根据系统时间和MAC地址创建UUID

import uuid

# 使用uuid1创建随机id
UID = uuid.uuid1()

# 打印标准ID
print ("标准值: ", UID)

# 打印字节ID
print ("字节ID: ", repr(UID.bytes))

# 打印整数ID
print ("整数值: ", UID.int)

# Print the hex ID
print ("十六进制值: ", UID.hex)

# 打印版本号
print ("版本号为 :", UID.version)

# 打印字段值
print ("字段是 ", UID.fields)

# 以十六进制打印MAC值
print ("节点值为: ", hex(UID.node))

# 打印时间值
print ("时间值为: ", UID.time)



# 结果如下
('\xe6\xa0\x87\xe5\x87\x86\xe5\x80\xbc: ', UUID('ce96a4ab-cf47-11ec-9f71-acde48001122'))
('\xe5\xad\x97\xe8\x8a\x82ID: ', '\'\\xce\\x96\\xa4\\xab\\xcfG\\x11\\xec\\x9fq\\xac\\xdeH\\x00\\x11"\'')
('\xe6\x95\xb4\xe6\x95\xb0\xe5\x80\xbc: ', 274603151587812998186977116984306569506L)
('\xe5\x8d\x81\xe5\x85\xad\xe8\xbf\x9b\xe5\x88\xb6\xe5\x80\xbc: ', 'ce96a4abcf4711ec9f71acde48001122')
('\xe7\x89\x88\xe6\x9c\xac\xe5\x8f\xb7\xe4\xb8\xba :', 1)
('\xe5\xad\x97\xe6\xae\xb5\xe6\x98\xaf ', (3465979051L, 53063L, 4588L, 159L, 113L, 190070690681122L))
('\xe8\x8a\x82\xe7\x82\xb9\xe5\x80\xbc\xe4\xb8\xba: ', '0xacde48001122L')
('\xe6\x97\xb6\xe9\x97\xb4\xe5\x80\xbc\xe4\xb8\xba: ', 138713595857249451L)

4.2、使用uuid3和uuid5生成主机名的SHA-1和MD5值

import uuid

# 定义三个主机名的元组
hosts = ('www.linuxmi.com', 'www.google.com', 'www.kotlin.ai')

# 使用loop迭代元组的值
for hostname in hosts:
    # 打印主机名
    print("主机名: ", hostname)
    # 使用uuid5获得SHA- 1值
    print('tSHA-1值 :', uuid.uuid5(uuid.NAMESPACE_DNS, hostname))
    # 使用uuid3获取MD5值
    print('tMD5值 :', uuid.uuid3(uuid.NAMESPACE_DNS, hostname))
    
    
    
# 结果如下
('\xe4\xb8\xbb\xe6\x9c\xba\xe5\x90\x8d: ', 'www.linuxmi.com')
('tSHA-1\xe5\x80\xbc :', UUID('2e7f9640-0358-54bb-ac54-10274483cc0f'))
('tMD5\xe5\x80\xbc :', UUID('008f758f-b1e7-367b-b3ca-6fb529777928'))
('\xe4\xb8\xbb\xe6\x9c\xba\xe5\x90\x8d: ', 'www.google.com')
('tSHA-1\xe5\x80\xbc :', UUID('488416f4-fcaf-5027-8c63-0105cfa213ea'))
('tMD5\xe5\x80\xbc :', UUID('de87628d-5377-3ba7-b31b-cde1cc8d423f'))
('\xe4\xb8\xbb\xe6\x9c\xba\xe5\x90\x8d: ', 'www.kotlin.ai')
('tSHA-1\xe5\x80\xbc :', UUID('d670314f-80be-5863-ba31-9b46be9fa355'))
('tMD5\xe5\x80\xbc :', UUID('ee11a1b9-3ce6-39b7-b311-cded3c178ba5'))

4.3、使用uuid4创建随机数

import uuid

i = 1

# 循环五次
while i < 6:
    # 产生一个随机数
    print("No-", i, ' ', uuid.uuid4)
    # 将值增加一 
    i = i + 1
    
    
# 结果如下
('No-', 1, ' ', <function uuid4 at 0x105050c50>)
('No-', 2, ' ', <function uuid4 at 0x105050c50>)
('No-', 3, ' ', <function uuid4 at 0x105050c50>)
('No-', 4, ' ', <function uuid4 at 0x105050c50>)
('No-', 5, ' ', <function uuid4 at 0x105050c50>)

4.4、使用UUID对象从列表中创建排序的UUID

import uuid

# 创建一个有效格式的id list
list_Ids = [

    'a4f8dd97-c8be-345b-239e-8a68e6abf800',

    '673a5eaa-56c6-aaaa-bc45-4536cd9067ac',

    'dcbbaa88-5bf1-11dd-ab48-990ab200d674',

    '4567aabb-89ad-77ab-67ad-aaaccdd904ae'

]

# 使用loop打印列表值
print('nlist的值:')
for val in list_Ids:
    print (val)
# list的值将被转换为uuid并进行排序
try:
    uuids = [uuid.UUID(s) for s in list_Ids]
    uuids.sort
    print('n已排序uuid的值:')
    for val in uuids:
        print (val)
except ValueError:
    # 如果list的任何值的格式无效,则打印错误消息
    print('格式不正确的十六进制UUID字符串')
    
    
    
# 结果如下
nlist的值:
a4f8dd97-c8be-345b-239e-8a68e6abf800
673a5eaa-56c6-aaaa-bc45-4536cd9067ac
dcbbaa88-5bf1-11dd-ab48-990ab200d674
4567aabb-89ad-77ab-67ad-aaaccdd904ae
n已排序uuid的值:
a4f8dd97-c8be-345b-239e-8a68e6abf800
673a5eaa-56c6-aaaa-bc45-4536cd9067ac
dcbbaa88-5bf1-11dd-ab48-990ab200d674
4567aabb-89ad-77ab-67ad-aaaccdd904ae

五、参考文档

1、https://blog.csdn.net/catwan/article/details/84998986

2、https://www.cnblogs.com/Security-Darren/p/4252868.html

3、https://baike.baidu.com/item/RFC/1840?fr=aladdin

4、https://www.sohu.com/a/400851011_495675

5、https://segmentfault.com/a/1190000000484508

6、https://blog.csdn.net/weixin_44621343/article/details/115958618

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值