如何在Python中生成唯一的64位整数?

57

我需要从Python生成唯一的64位整数。我已经查看了UUID模块,但是它生成的UUID为128位整数,因此不能使用。

您知道在Python中生成64位唯一整数的任何方法吗?谢谢。


2
它们需要有多独特?是针对该程序的独特性,还是针对任何计算机上任何程序生成的每个ID的独特性(这就是UUID所提供的)? - Dave Kirby
Dave - 这些是文档 ID。每个生成的 ID 都需要是唯一的。我可以有多个服务器,每个服务器都有 Python 进程。 - Continuation
为什么不直接分配顺序数字呢?它们是唯一的。 - S.Lott
2
@S.Lott - 你如何协调不同机器上的不同 Python 进程,以分配顺序数字? - Continuation
1
(1) 那有什么关系呢?这是必须的吗?如果是必须的,那为什么问题中没有提到这个要求呢? (2) 这就是数据库服务器的作用。 - S.Lott
5个回答

78

只需将128位整数屏蔽掉即可。

>>> import uuid
>>> uuid.uuid4().int & (1<<64)-1
9518405196747027403L
>>> uuid.uuid4().int & (1<<64)-1
12558137269921983654L

这些几乎是随机的,因此您有很小的碰撞几率

也许 uuid1 的前 64 位更安全可靠地使用

>>> uuid.uuid1().int>>64
9392468011745350111L
>>> uuid.uuid1().int>>64
9407757923520418271L
>>> uuid.uuid1().int>>64
9418928317413528031L

这些主要基于时钟,因此不太随机,但独特性更好。


3
UUID1会显示MAC地址和时间戳,而UUID4更加安全。 - Lukas Cenovsky
7
将64位向右移动可以去除MAC地址和时间,只留下时钟信息。 - Glyph
@LukasCenovsky,uuid1 更可能唯一,正因为这个原因。取决于是否需要安全性,但 uuid4 的折衷是碰撞更有可能发生。 - John La Rooy
1
@JohnLaRooy,uuid1部分是不正确或误导的,因为它创建的是无符号整数,而不是整数(整数默认应该是有符号的)。我认为正确的方法应该是这样的: int.from_bytes(uuid.uuid1().bytes, byteorder='big', signed=True) >> 64 - Stan Prokop
@JohnLaRooy,如果您认为stanProkop的回答可以改进您的答案,您是否愿意更新它?我猜这个额外的部分会使它更好。 - Robert Lugg

30

64位唯一标识

计数有什么问题吗?一个简单的计数器将创建唯一的值。这是最简单的方法,可以确保您不会重复值。

或者,如果计数还不够好,可以尝试这个。

>>> import random
>>> random.getrandbits(64)
5316191164430650570L

根据您如何生成和使用随机数生成器,它应该是唯一的。

当然,您可能会不正确地执行此操作并获得重复的随机数序列。在处理程序的种子以启动和停止程序时需要非常小心。


1
无论你的种子有多好,如果你使用getrandbits()方法生成了约2^32个ID,那么很可能会出现重复。 - President James K. Polk
2
该序列在理论上更长。"它生成53位精度的浮点数,并具有2 ** 19937-1的周期。"为什么getrandbits()没有完整的周期?它是否生成多个数字?即使它生成64个不同的值并仅使用一个位,结果的周期也将是2 ^ 311。 - S.Lott
种子有多大?如果使用相同的种子,你将得到相同的随机数。 - dalore
1
你怎么实现这个“just count”? - buhtz
“为什么 getrandbits() 函数没有完整周期?”可能会有完整的周期,但只存在 2**64 个独特的 64 位整数,所以你无法获得一个由 2**19937-1 个唯一整数组成的序列。假设随机分布,你会预计在 2**32 左右开始出现重复现象。 - towr

9

使用操作系统的随机数生成器生成一个64位的随机数,而不是伪随机数生成器:

>>> from struct import unpack; from os import urandom
>>> unpack("!Q", urandom(8))[0]
12494068718269657783L

2
您可以使用uuid4()生成一个随机的128位整数UUID。我们需要对每个128位整数进行“二进制右移”操作(>>),使其变为64位(即128 - (128 - 64))。
from uuid import uuid4

bit_size = 64
sized_unique_id = uuid4().int >> bit_size
print(sized_unique_id)

1
最好直接使用例如os.urandom(8)secrets.randbelow(2**64)来直接生成字节。首先,uuid4的128位中仅有122位是随机生成的,而另外6位是固定的。你的方法只提供了60个随机位而不是64个,这会增加随机碰撞的可能性。 - Mark Dickinson
位数不是64,而是60~64。 - Xiao

0

为什么不试试这个?

import uuid
  
id = uuid.uuid1()
  
# Representations of uuid1()

print (repr(id.bytes)) # k\x10\xa1n\x02\xe7\x11\xe8\xaeY\x00\x16>\x99\x0b\xdb

print (id.int)         # 142313746482664936587190810281013480411  

print (id.hex)         # 6b10a16e02e711e8ae5900163e990bdb
  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接