Hoe een willekeurige UUID te genereren die reproduceerbaar is (met een seed) in Python

De uuid4()functie van Python’s module uuidgenereert een willekeurige UUID en lijkt elke keer een andere te genereren:

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')

Ik zou graag dezelfde willekeurige UUID willen genereren elke keer dat ik een script uitvoer – dat wil zeggen, ik zou de willekeurige generator in uuid4()willen plaatsen. Is er een manier om dit te doen? (Of dit op een andere manier bereiken)?

Wat ik tot nu toe heb geprobeerd

Ik moet een UUID genereren met behulp van de methode uuid.UUID()met een willekeurig 128-bits geheel getal (van een geplaatste instantie van random.Random()) als invoer:

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

Echter, UUID()lijkt dit niet als invoer te accepteren:

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'

Heeft u nog andere suggesties?


Antwoord 1, autoriteit 100%

Bijna daar:

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

Dit is vastgesteld met behulp van 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'.

Antwoord 2, autoriteit 56%

Fakermaakt dit gemakkelijk

>>> 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

Antwoord 3, autoriteit 34%

Dit is gebaseerd op een oplossing die hier:

wordt gebruikt

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

Antwoord 4, autoriteit 12%

Ik voeg dit hier toe als iemand een patch moet gebruiken in een geplaatste UUID. Mijn code gebruikt uuid.uuid4()maar voor het testen wilde ik consistente UUID’s. De volgende code is hoe ik dat deed:

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)

Antwoord 5, autoriteit 10%

Omdat de eenvoudige oplossing nog niet is gepost om consistente versie 4 UUID’s te genereren:

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)

waar je dan kunt zien:

>>> uuid.version
4

Dit “bespot” niet alleen de versie-informatie. Het creëert een juiste UUIDv4:

Het versieargument is optioneel; indien opgegeven, heeft de resulterende UUID zijn variant- en versienummer ingesteld volgens RFC 4122, waarbij bits in de gegeven hex, bytes, bytes_le, velden of int worden overschreven.

Python 3.8-documenten


Antwoord 6, autoriteit 7%

Op basis van de oplossing van alex zou het volgende een juiste UUID4 bieden:

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

Antwoord 7, autoriteit 5%

Eenvoudige oplossing gebaseerd op het antwoord van @user10229295, met een opmerking over de seed.
De wachtrij Bewerken was vol, dus ik opende een nieuw antwoord:

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())

Opmerking over de string ‘seed’:
Het zal de seed zijn waaruit de UUID wordt gegenereerd: uit dezelfde seed-string wordt altijd dezelfde UUID gegenereerd. U kunt een geheel getal met enige betekenis als tekenreeks converteren, verschillende tekenreeksen samenvoegen en het resultaat als uw seed gebruiken. Hiermee heb je controle over de gegenereerde UUID, wat betekent dat je je UUID kunt reproduceren, wetende welke seed je hebt gebruikt: met dezelfde seed zal de daaruit gegenereerde UUID hetzelfde zijn.

Other episodes