UUID
Universally Unique Identifier (UUID),即通用唯一识别码,是一种软件建构的标准。它的目的在于让分布式系统中的所有元素,都能有唯一的辨识信息,而不需要中央控制端做辨识信息的制定。每个人都可以创建与其他人不冲突(重复)的UUID,因此常用作对某一东西的唯一标识。
UUID常用作数据库的主键。
UUID常用作一次计算任务的唯一标识。
Python uuid
Python中内置了一个名为uuid
包来处理UUID的生成,使用起来非常方便,它提供了生成36位uuid的方法(32位加上4个’-'号作为间隔符,如果不需要间隔符可以手动去掉)。
Python的uuid
包一共提供了4中生成UUID的方法:
- uuid1()
- uuid3()
- uuid4()
- uuid5()
注:没有uuid2。
使用示例:
import uuidprint(uuid.uuid1())
print(uuid.uuid3(uuid.NAMESPACE_DNS, "test"))
print(uuid.uuid4()) # b983907d-ab25-4002-9dad-c37968936ba8
print(uuid.uuid5(uuid.NAMESPACE_DNS, "test"))
为了信息安全,uuid4之外的结果没有贴出来,读者可以本地自行试试。
注意:生成的uuid不是字符串类型,如果以字符串形式落库或者传递需要手动转换一下:
import uuidprint(type(uuid.uuid4()))
print(str(uuid.uuid4()))
四种生成uuid方法间的区别
官方文档见:https://docs.python.org/3/library/uuid.html?highlight=uuid#module-uuid
- uuid1根据当前时间的时间戳加上电脑的mac地址生成,最后12位字符对应mac地址。因为是mac地址,所以本身具备唯一性。但是用这种方法生成uuid并分享泄露了自己的mac地址,因此不推荐使用。
- uuid3根据传入的namespace和一个由调用者指定字符串调用MD5算法生成。
- uuid4则是根据随机数生成的,因为不需要参数所以使用起来很方便,但需要注意的是,因为是随机数,所以极其小的概率下也可能会重复。
- uuid5同样根据传入的namespace和一个由调用者指定字符串生成uuid,如uuid3不同的是,它使用SHA1算法。
源码列在下面👇🏻:
def uuid1(node=None, clock_seq=None):"""Generate a UUID from a host ID, sequence number, and the current time.If 'node' is not given, getnode() is used to obtain the hardwareaddress. If 'clock_seq' is given, it is used as the sequence number;otherwise a random 14-bit sequence number is chosen."""# When the system provides a version-1 UUID generator, use it (but don't# use UuidCreate here because its UUIDs don't conform to RFC 4122)._load_system_functions()if _generate_time_safe is not None and node is clock_seq is None:uuid_time, safely_generated = _generate_time_safe()try:is_safe = SafeUUID(safely_generated)except ValueError:is_safe = SafeUUID.unknownreturn UUID(bytes=uuid_time, is_safe=is_safe)global _last_timestampimport timenanoseconds = int(time.time() * 1e9)# 0x01b21dd213814000 is the number of 100-ns intervals between the# UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.timestamp = int(nanoseconds/100) + 0x01b21dd213814000if _last_timestamp is not None and timestamp <= _last_timestamp:timestamp = _last_timestamp + 1_last_timestamp = timestampif clock_seq is None:import randomclock_seq = random.getrandbits(14) # instead of stable storagetime_low = timestamp & 0xfffffffftime_mid = (timestamp >> 32) & 0xfffftime_hi_version = (timestamp >> 48) & 0x0fffclock_seq_low = clock_seq & 0xffclock_seq_hi_variant = (clock_seq >> 8) & 0x3fif node is None:node = getnode()return UUID(fields=(time_low, time_mid, time_hi_version,clock_seq_hi_variant, clock_seq_low, node), version=1)def uuid3(namespace, name):"""Generate a UUID from the MD5 hash of a namespace UUID and a name."""from hashlib import md5hash = md5(namespace.bytes + bytes(name, "utf-8")).digest()return UUID(bytes=hash[:16], version=3)def uuid4():"""Generate a random UUID."""return UUID(bytes=os.urandom(16), version=4)def uuid5(namespace, name):"""Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""from hashlib import sha1hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()return UUID(bytes=hash[:16], version=5)# The following standard UUIDs are for use with uuid3() or uuid5().NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')
def uuid1(node=None, clock_seq=None):"""Generate a UUID from a host ID, sequence number, and the current time.If 'node' is not given, getnode() is used to obtain the hardwareaddress. If 'clock_seq' is given, it is used as the sequence number;otherwise a random 14-bit sequence number is chosen."""# When the system provides a version-1 UUID generator, use it (but don't# use UuidCreate here because its UUIDs don't conform to RFC 4122)._load_system_functions()if _generate_time_safe is not None and node is clock_seq is None:uuid_time, safely_generated = _generate_time_safe()try:is_safe = SafeUUID(safely_generated)except ValueError:is_safe = SafeUUID.unknownreturn UUID(bytes=uuid_time, is_safe=is_safe)global _last_timestampimport timenanoseconds = int(time.time() * 1e9)# 0x01b21dd213814000 is the number of 100-ns intervals between the# UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.timestamp = int(nanoseconds/100) + 0x01b21dd213814000if _last_timestamp is not None and timestamp <= _last_timestamp:timestamp = _last_timestamp + 1_last_timestamp = timestampif clock_seq is None:import randomclock_seq = random.getrandbits(14) # instead of stable storagetime_low = timestamp & 0xfffffffftime_mid = (timestamp >> 32) & 0xfffftime_hi_version = (timestamp >> 48) & 0x0fffclock_seq_low = clock_seq & 0xffclock_seq_hi_variant = (clock_seq >> 8) & 0x3fif node is None:node = getnode()return UUID(fields=(time_low, time_mid, time_hi_version,clock_seq_hi_variant, clock_seq_low, node), version=1)def uuid3(namespace, name):"""Generate a UUID from the MD5 hash of a namespace UUID and a name."""from hashlib import md5hash = md5(namespace.bytes + bytes(name, "utf-8")).digest()return UUID(bytes=hash[:16], version=3)def uuid4():"""Generate a random UUID."""return UUID(bytes=os.urandom(16), version=4)def uuid5(namespace, name):"""Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""from hashlib import sha1hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()return UUID(bytes=hash[:16], version=5)# The following standard UUIDs are for use with uuid3() or uuid5().NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')