Python随机字符串重复7/2000条记录

时间:2016-03-01 22:57:24

标签: python django string random django-models

我使用以下内容生成一组随机字符和数字:

tag = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(36)])

我认为这是一个不错的方法。 36个字符长度,每个字符是36个独特选项之一。应该是一个很好的随机性,对吗?

然后,我正在使用我认为是唯一tag的实例运行查询。事实证明, SEVEN(7)记录具有相同的"随机" tag。所以,我打开了数据库,并运行了一个查询来查看我的标签的可重复性。

事实证明,我的不仅会出现7次,而且会有一些标签反复出现。大约有2000行,显然不应该发生这种情况。

两个问题:

(1)我的方法出了什么问题,为什么会经常重复相同的tag

(2)为每条记录获取唯一标记的更好方法是什么?

以下是我用来将其保存到数据库的代码。虽然它是用Django编写的,但显然这不是与django相关的问题。

class Note(models.Model):
    ...
    def save(self, *args, **kwargs):
        import random
        import string
        self.tag = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(36)])
        super(Note, self).save(*args, **kwargs)

2 个答案:

答案 0 :(得分:1)

您的方法存在问题:

  1. 真正的随机性/加密很难,您应该尝试使用经过测试的现有解决方案而不是实现自己的解决方案。
  2. 无法保证随机性 - 虽然“不太可能”,但没有什么能阻止同一个字符串多次生成。
  3. 更好的解决方案是不重新发明轮子,并使用uuid模块,这是生成唯一标识符的常用解决方案:

    import uuid
    
    tag = uuid.uuid1()
    

答案 1 :(得分:0)

使用加密安全的PRNGrandom.SystemRandom()。它将使用你所使用的任何系统的PRNG。

tag = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for n in xrange(36))

请注意,无需将此作为列表理解传递给join()

62 36 可能的组合,一个65位的数字,所以即使考虑birthday paradox,重复也应该非常少见。