• Python3标准库:uuid 全局唯一标识符


    1. uuid 全局唯一标识符

    uuid 模块实现了全局唯一标识符(Universally Unique Identifier);这个RFC定义了一个系统,可以为资源创建唯一的标识符,这里采用一种不需要集中注册机的方式。UUID值为128位,正如参考指南所述,“UUID可以保证跨空间和时间的唯一性”。对于文档、主机、应用客户以及其他需要唯一值的情况,UUID可以用来生成标识符。这个RFC特别强调创建一个统一资源名(Uniform Resource Name)命名空间,并且涵盖了3个主要算法。

    • 使用IEEE802MAC地址作为唯一性来源
    • 使用伪随机数
    • 使用公开的串并结合密码散列

    在上述所有情况下,种子值都要与系统时钟结合,如果向后设置时钟,则要用一个时钟序列值维护唯一性。

    1.1 UUID1: IEEE 802 MAC地址

    UUID1值使用主机的MAC地址计算。uuid模块使用getnode()来获取当前系统的MAC值。

    import uuid
    
    print(hex(uuid.getnode()))

    如果一个系统有多个网卡,那么相应地便会有多个MAC地址,并且可能返回其中任意一个值。

    要为一个主机(由其MAC地址标识)生成一个UUID,需要使用uuid1()函数。节点标识符参数是可选的;如果没有设置这个域,那么便会使用getnode()返回的值。

    import uuid
    
    u = uuid.uuid1()
    
    print(u)
    print(type(u))
    print('bytes   :', repr(u.bytes))
    print('hex     :', u.hex)
    print('int     :', u.int)
    print('urn     :', u.urn)
    print('variant :', u.variant)
    print('version :', u.version)
    print('fields  :', u.fields)
    print('  time_low            : ', u.time_low)
    print('  time_mid            : ', u.time_mid)
    print('  time_hi_version     : ', u.time_hi_version)
    print('  clock_seq_hi_variant: ', u.clock_seq_hi_variant)
    print('  clock_seq_low       : ', u.clock_seq_low)
    print('  node                : ', u.node)
    print('  time                : ', u.time)
    print('  clock_seq           : ', u.clock_seq)

    对于返回的UUID对象,可以通过只读的实例属性访问它的各个部分。有些属性是UUID值的不同表示,如hex、int和urn。

    由于有时间分量(time),所以每次调用uuid1()都会返回一个新值。

    import uuid
    
    for i in range(3):
        print(uuid.uuid1())

    在这个输出中,只有时间分量(串的开始部分)有变化。

    由于每个计算机有不同的MAC地址,所以在不同系统上运行这个示例程序会生成完全不同的值。下一个例子传递不同的节点ID来模拟在不同主机上运行。

    import uuid
    
    for node in [0x1ec200d9e0, 0x1e5274040e]:
        print(uuid.uuid1(node), hex(node))

    除了返回不同的时间值,UUID末尾的节点标识符也有变化。

    1.2 UUID 3和5 基于名字的值

    有些情况下可能需要根据名字创建UUID值,而不是根据随机值或基于时间的值来创建。UUID3和5规范使用密码散列值(分别使用MD5或SHA-1),将特定于命名空间的种子值与名字相结合。有一些由预定义UUID值标识的公开的命名空间,分别用于处理DNS、URL、ISO OID和X.500识别名(Distinguished Name)。通过生成和保存UUID值,还可以定义新的特定于应用的命名空间。

    import uuid
    
    hostnames = ['www.doughellmann.com', 'blog.doughellmann.com']
    
    for name in hostnames:
        print(name)
        print('  MD5   :', uuid.uuid3(uuid.NAMESPACE_DNS, name))
        print('  SHA-1 :', uuid.uuid5(uuid.NAMESPACE_DNS, name))
        print()

    要从一个DNS名创建UUID,可以把uuid.NAMESPACE_DNS作为命名空间参数传入uuid3()或uuid5()。

    不论什么时间计算或者在哪里计算,一个命名空间中给定名的UUID值总是相同的。

    import uuid
    
    namespace_types = sorted(
        n
        for n in dir(uuid)
        if n.startswith('NAMESPACE_')
    )
    name = 'www.doughellmann.com'
    
    for namespace_type in namespace_types:
        print(namespace_type)
        namespace_uuid = getattr(uuid, namespace_type)
        print(' ', uuid.uuid3(namespace_uuid, name))
        print(' ', uuid.uuid3(namespace_uuid, name))
        print()

    但是命名空间中相同名字的UUID值则是不同的。

    1.3 UUID 4 随机数

    有时,基于主机和基于命名空间的UUID值“差别还不够大”。例如,如果UUID要作为散列键,则需要有区分度更大、更随机的值序列来避免散列表中出现冲突。让值有更少的共同数字也能更容易地在日志文件中查找这些值。为了增加UUID的区分度,可以使用uuid4()利用随机的输入值生成UUID。

    import uuid
    
    for i in range(3):
        print(uuid.uuid4())

    随机性的来源取决于导入uuid时哪些C库可用。如果可以加载libuuid(或uuid.d11),而且其中包含一个生成随机值的函数,那么便使用这个函数。否则,使用os.urandom()或random模块。

    1.4 处理UUID对象

    除了生成新的UUID值,还可以解析标准格式的串以创建UUID对象,使比较和排序操作的处理更为容易。

    import uuid
    
    def show(msg, l):
        print(msg)
        for v in l:
            print(' ', v)
        print()
    
    input_values = [
        'urn:uuid:f2f84497-b3bf-493a-bba9-7c68e6def80b',
        '{417a5ebb-01f7-4ed5-aeac-3d56cd5037b0}',
        '2115773a-5bf1-11dd-ab48-001ec200d9e0',
    ]
    
    show('input_values', input_values)
    
    uuids = [uuid.UUID(s) for s in input_values]
    show('converted to uuids', uuids)
    
    uuids.sort()
    show('sorted', uuids)

    从输入中去除外围大括号,另外将短横线(-)也去除。如果串有一个包含urn:或uuid:的前缀,则这个前缀也会被删除。剩下的文本必然是由十六进制数构成的串,然后再将它解释为一个UUID值。

  • 相关阅读:
    YC创始人格雷厄姆为何不喜欢大学生创业?
    在创业的道路上,让公司生存下去是做重要的!
    农村90后李传帅的创业故事
    创业公司的出头之日在哪里?
    创业者不能盲目的跟风,不然结局很凄凉
    小程序到底适不适合创业者
    共享经济的涨潮与退潮就在一瞬间
    互联网行业进入焦虑时代,如何才能做到攻守有道?
    88
    JZOJ.5331【NOIP2017模拟8.23】壕游戏
  • 原文地址:https://www.cnblogs.com/liuhui0308/p/12665600.html
Copyright © 2020-2023  润新知