【问题标题】:How to generate a random UUID which is reproducible (with a seed) in Python如何在 Python 中生成可重现(带有种子)的随机 UUID
【发布时间】:2017-05-02 09:26:20
【问题描述】:

Python的模块uuiduuid4()函数会生成一个随机的UUID,而且好像每次都生成一个不同的:

In [1]: import uuid

In [2]: uuid.uuid4()
Out[2]: UUID('f6c9ad6c-eea0-4049-a7c5-56253bc3e9c0')

In [3]: uuid.uuid4()
Out[3]: UUID('2fc1b6f9-9052-4564-9be0-777e790af58f')

我希望能够在每次运行脚本时生成相同的随机 UUID - 也就是说,我希望在 uuid4() 中播种随机生成器。有没有办法做到这一点? (或者通过其他方式实现)?

到目前为止我已经尝试过什么

我必须使用 uuid.UUID() 方法生成一个 UUID,并使用随机 128 位整数(来自 random.Random() 的种子实例)作为输入:

import uuid
import random

rd = random.Random()
rd.seed(0)
uuid.UUID(rd.getrandbits(128))

但是,UUID() 似乎不接受这个作为输入:

Traceback (most recent call last):
  File "uuid_gen_seed.py", line 6, in <module>
    uuid.UUID(rd.getrandbits(128))
  File "/usr/lib/python2.7/uuid.py", line 133, in __init__
    hex = hex.replace('urn:', '').replace('uuid:', '')
AttributeError: 'long' object has no attribute 'replace'

还有其他建议吗?

【问题讨论】:

  • 它显然需要某种字符串,hex 的提及表明您可以通过调用hey(rd.getrandbits(128)) 来获取它。但是,您最终不会得到 uuid4。
  • 你需要一种方法来产生一个随机的十六进制数字(小写)。您需要第二种方法从 {8, 9, a, b} 中产生随机选择。将它们按正确的顺序放在一起,加上字符“-”和“4”,您就可以制作自己的 UUID4 方法。

标签: python random uuid


【解决方案1】:

由于尚未发布生成一致的第 4 版 UUID 的直接解决方案:

import random
import uuid

rnd = random.Random()
rnd.seed(123) # NOTE: Of course don't use a static seed in production

uuid = uuid.UUID(int=rnd.getrandbits(128), version=4)

你可以在哪里看到:

>>> uuid.version
4

这不仅仅是“模拟”版本信息。它会创建一个合适的 UUIDv4:

版本参数是可选的;如果给定,则生成的 UUID 将根据 RFC 4122 设置其变体和版本号,覆盖给定 hex、bytes、bytes_le、fields 或 int 中的位。

Python 3.8 docs

【讨论】:

    【解决方案2】:

    基于@user10229295 的答案的简单解决方案,并带有关于种子的评论。 编辑队列已满,所以我打开了一个新答案:

    import hashlib
    import uuid
    
    seed = 'Type your seed_string here' #Read comment below
    
    m = hashlib.md5()
    m.update(seed.encode('utf-8'))
    new_uuid = uuid.UUID(m.hexdigest())
    

    评论字符串'seed': 它将是生成 UUID 的种子:从相同的种子字符串将始终生成相同的 UUID。您可以将具有某种意义的整数转换为字符串,连接不同的字符串并将结果用作种子。有了这个,您将可以控制生成的 UUID,这意味着您将能够在知道您使用的种子的情况下重现您的 UUID:使用相同的种子,从它生成的 UUID 将是相同的。

    【讨论】:

      【解决方案3】:

      如果有人需要在种子 UUID 中进行猴子补丁,我会在此处添加此内容。我的代码使用uuid.uuid4(),但为了测试,我想要一致的 UUID。以下代码是我的做法:

      import uuid
      import random
      
      # -------------------------------------------
      # Remove this block to generate different
      # UUIDs everytime you run this code.
      # This block should be right below the uuid
      # import.
      rd = random.Random()
      rd.seed(0)
      uuid.uuid4 = lambda: uuid.UUID(int=rd.getrandbits(128))
      # -------------------------------------------
      
      # Then normal code:
      
      print(uuid.uuid4().hex)
      print(uuid.uuid4().hex)
      print(uuid.uuid4().hex)
      print(uuid.uuid4().hex)
      

      【讨论】:

        【解决方案4】:

        这是基于使用的解决方案here

        import hashlib
        import uuid
        
        m = hashlib.md5()
        m.update(seed.encode('utf-8'))
        new_uuid = uuid.UUID(m.hexdigest())
        

        【讨论】:

        • 这里的seed 是什么?
        【解决方案5】:

        Faker 让这一切变得简单

        >>> from faker import Faker
        >>> f1 = Faker()
        >>> f1.seed(4321)
        >>> print(f1.uuid4())
        cc733c92-6853-15f6-0e49-bec741188ebb
        >>> print(f1.uuid4())
        a41f020c-2d4d-333f-f1d3-979f1043fae0
        >>> f1.seed(4321)
        >>> print(f1.uuid4())
        cc733c92-6853-15f6-0e49-bec741188ebb
        

        【讨论】:

          【解决方案6】:

          根据 alex 的解决方案,以下将提供正确的 UUID4:

          random.seed(123210912)
          a = "%32x" % random.getrandbits(128)
          rd = a[:12] + '4' + a[13:16] + 'a' + a[17:]
          uuid4 = uuid.UUID(rd)
          

          【讨论】:

            【解决方案7】:

            差不多了:

            uuid.UUID(int=rd.getrandbits(128))
            

            这是在help的帮助下确定的:

            >>> help(uuid.UUID.__init__)
            Help on method __init__ in module uuid:
            
            __init__(self, hex=None, bytes=None, bytes_le=None, fields=None, int=None, version=None) unbound uuid.UUID method
                Create a UUID from either a string of 32 hexadecimal digits,
                a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
                in little-endian order as the 'bytes_le' argument, a tuple of six
                integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
                8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
                the 'fields' argument, or a single 128-bit integer as the 'int'
                argument.  When a string of hex digits is given, curly braces,
                hyphens, and a URN prefix are all optional.  For example, these
                expressions all yield the same UUID:
            
                UUID('{12345678-1234-5678-1234-567812345678}')
                UUID('12345678123456781234567812345678')
                UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
                UUID(bytes='\x12\x34\x56\x78'*4)
                UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
                              '\x12\x34\x56\x78\x12\x34\x56\x78')
                UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
                UUID(int=0x12345678123456781234567812345678)
            
                Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
                be given.  The 'version' argument is optional; if given, the resulting
                UUID will have its variant and version set according to RFC 4122,
                overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
            

            【讨论】:

            • 这可行,但不会(必然)返回 UUID4 (see also)。
            • @L3viathan 我不明白为什么不,你能解释一下吗?
            • UUID4 并不意味着它是完全随机的,一些位是固定的。见the section in the Wikipedia article。我并不是说这对 OP 来说一定很重要,但我认为应该澄清一下,因为他们确实提到了 UUID4。
            • @L3viathan 如何修改 UUID 输出以使其成为有效(确定性)UUID4?
            • @pir 只要给它version参数:uuid.UUID(int=rd.getrandbits(128), version=4)
            猜你喜欢
            • 2020-02-16
            • 1970-01-01
            • 2021-05-15
            • 1970-01-01
            • 1970-01-01
            • 2017-08-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多