Come creare un GUID / UUID in Python


687

Come posso creare un GUID in Python indipendente dalla piattaforma? Ho sentito che esiste un metodo che utilizza ActivePython su Windows ma è Windows solo perché utilizza COM. Esiste un metodo che utilizza Python semplice?



35
Per l'amore di tutto ciò che è sacro, è un UUID - Universal Unique ID en.wikipedia.org/wiki/Universally_unique_identifier - è solo che purtroppo MS ha preferito GUID.
david.barkhuizen,

5
Ecco una frase per te:python -c 'import uuid; print(uuid.uuid4())'
Ctrl-C

Risposte:


777

Il modulo uuid, in Python 2.5 e versioni successive, fornisce una generazione UUID conforme a RFC. Vedere i documenti del modulo e la RFC per i dettagli. [ fonte ]

Documenti:

Esempio (lavorando su 2 e 3):

>>> import uuid
>>> uuid.uuid4()
UUID('bd65600d-8669-4903-8a14-af88203add38')
>>> str(uuid.uuid4())
'f50ec0b7-f960-400d-91f0-c42a6d44e3d0'
>>> uuid.uuid4().hex
'9fe2c4e93f654fdbb24c02b15259716c'

20
Inoltre, dai un'occhiata al shortuuidmodulo che ho scritto, in quanto ti consente di generare UUID più brevi e leggibili: github.com/stochastic-technologies/shortuuid
Stavros Korokithakis

2
@StavrosKorokithakis: hai mai scritto un modulo shortuuid per Python 3.x?
Jay Patel,

2
@JayPatel Lo shortuuid non funziona per Python 3? In caso contrario, si prega di presentare un bug.
Stavros Korokithakis,

1
Qual è la differenza tra uuid4().hexe str(uuid4())?
Kevin

6
Bene, come puoi vedere sopra, str(uuid4())restituisce una rappresentazione di stringa dell'UUID con i trattini inclusi, mentre uuid4().hexrestituisce "L'UUID come una stringa esadecimale di 32 caratteri"
stuartd

324

Se stai usando Python 2.5 o successivo, il modulo uuid è già incluso nella distribuzione standard di Python.

Ex:

>>> import uuid
>>> uuid.uuid4()
UUID('5361a11b-615c-42bf-9bdb-e2c3790ada14')

116

Copiato da: https://docs.python.org/2/library/uuid.html (Poiché i collegamenti pubblicati non erano attivi e continuano ad aggiornarsi)

>>> import uuid

>>> # make a UUID based on the host ID and current time
>>> uuid.uuid1()
UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')

>>> # make a UUID using an MD5 hash of a namespace UUID and a name
>>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')

>>> # make a random UUID
>>> uuid.uuid4()
UUID('16fd2706-8baf-433b-82eb-8c7fada847da')

>>> # make a UUID using a SHA-1 hash of a namespace UUID and a name
>>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')

>>> # make a UUID from a string of hex digits (braces and hyphens ignored)
>>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')

>>> # convert a UUID to a string of hex digits in standard form
>>> str(x)
'00010203-0405-0607-0809-0a0b0c0d0e0f'

>>> # get the raw 16 bytes of the UUID
>>> x.bytes
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'

>>> # make a UUID from a 16-byte string
>>> uuid.UUID(bytes=x.bytes)
UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')

28

Uso i GUID come chiavi casuali per operazioni di tipo database.

La forma esadecimale, con i trattini e i caratteri extra, mi sembra inutilmente lunga. Ma mi piace anche che le stringhe che rappresentano numeri esadecimali siano molto sicure in quanto non contengono caratteri che possono causare problemi in alcune situazioni come '+', '=', ecc.

Invece di esadecimali, uso una stringa base64 url-safe. Quanto segue non è conforme a nessuna specifica UUID / GUID (tranne che con la quantità richiesta di casualità).

import base64
import uuid

# get a UUID - URL safe, Base64
def get_a_uuid():
    r_uuid = base64.urlsafe_b64encode(uuid.uuid4().bytes)
    return r_uuid.replace('=', '')

2
Se non ti preoccuperai di usarlo in qualsiasi contesto UUID, puoi anche semplicemente usare random.getrandbits(128).to_bytes(16, 'little')o (per la casualità crittografica) os.urandom(16)e ottenere 128 bit completi di casuale (UUIDv4 usa 6-7 bit nelle informazioni sulla versione). Oppure usa solo 15 byte (perdendo 1-2 bit di random rispetto a UUIDv4) ed evita la necessità di tagliare i =segni riducendo allo stesso tempo la dimensione codificata a 20 byte (da 24, ritagliata a 22), poiché ogni multiplo di 3 byte codifica a #bytes / 3 * 464 caratteri base64 senza riempimento richiesto.
ShadowRanger

@ShadowRanger Sì, questa è sostanzialmente l'idea. 128 bit casuali, il più corti possibile, pur essendo sicuri per gli URL. Idealmente userebbe solo lettere maiuscole e minuscole e poi numeri. Quindi immagino una stringa base-62.
Chris Dutrow,

Quando utilizzo la tua funzione ottengo un errore di tipo dall'istruzione in returnattesa di un oggetto simile a byte. Può essere riparato con return str(r_uuid).replace('=','').
Mark Kortink il

8

Se devi passare l'UUID per una chiave primaria per il tuo modello o campo univoco, il codice seguente restituisce l'oggetto UUID -

 import uuid
 uuid.uuid4()

Se devi passare l'UUID come parametro per l'URL, puoi fare come sotto il codice:

import uuid
str(uuid.uuid4())

Se vuoi il valore esadecimale per un UUID puoi fare quello sotto -

import uuid    
uuid.uuid4().hex

0

Questa funzione è completamente configurabile e genera un uid univoco in base al formato specificato

ad es .: - [8, 4, 4, 4, 12], questo è il formato menzionato e genererà il seguente uuid

LxoYNyXe-7hbQ-caJt-DSdU-PDAht56cMEWi

 import random as r

 def generate_uuid():
        random_string = ''
        random_str_seq = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        uuid_format = [8, 4, 4, 4, 12]
        for n in uuid_format:
            for i in range(0,n):
                random_string += str(random_str_seq[r.randint(0, len(random_str_seq) - 1)])
            if n != 12:
                random_string += '-'
        return random_string

3
Gli UUID sono standard e non di lunghezza variabile. Generare una stringa casuale in modo configurabile può essere utile in alcune situazioni, ma non in questo contesto. Puoi controllare en.wikipedia.org/wiki/Universally_unique_identifier per la definizione.
miguelr,

2
Meglio evitare questo o potresti incorrere in problemi di compatibilità (questi non sono GUID standard)
Sylvain Gantois,

-1

Risposta 2019 (per Windows):

Se vuoi un UUID permanente che identifichi una macchina in modo univoco su Windows, puoi usare questo trucco: (Copiato dalla mia risposta su https://stackoverflow.com/a/58416992/8874388 ).

from typing import Optional
import re
import subprocess
import uuid

def get_windows_uuid() -> Optional[uuid.UUID]:
    try:
        # Ask Windows for the device's permanent UUID. Throws if command missing/fails.
        txt = subprocess.check_output("wmic csproduct get uuid").decode()

        # Attempt to extract the UUID from the command's result.
        match = re.search(r"\bUUID\b[\s\r\n]+([^\s\r\n]+)", txt)
        if match is not None:
            txt = match.group(1)
            if txt is not None:
                # Remove the surrounding whitespace (newlines, space, etc)
                # and useless dashes etc, by only keeping hex (0-9 A-F) chars.
                txt = re.sub(r"[^0-9A-Fa-f]+", "", txt)

                # Ensure we have exactly 32 characters (16 bytes).
                if len(txt) == 32:
                    return uuid.UUID(txt)
    except:
        pass # Silence subprocess exception.

    return None

print(get_windows_uuid())

Utilizza l'API di Windows per ottenere l'UUID permanente del computer, quindi elabora la stringa per garantire che sia un UUID valido e infine restituisce un oggetto Python ( https://docs.python.org/3/library/uuid.html ) che ti dà comodo modi di utilizzare i dati (come numeri interi a 128 bit, stringhe esadecimali, ecc.).

In bocca al lupo!

PS: la chiamata al sottoprocesso potrebbe probabilmente essere sostituita con i tipi che chiamano direttamente kernel / DLL di Windows. Ma per i miei scopi questa funzione è tutto ciò di cui ho bisogno. Fa una forte convalida e produce risultati corretti.


-1

Controlla questo post, mi ha aiutato molto. In breve, l'opzione migliore per me era:

import random 
import string 

# defining function for random 
# string id with parameter 
def ran_gen(size, chars=string.ascii_uppercase + string.digits): 
    return ''.join(random.choice(chars) for x in range(size)) 

# function call for random string 
# generation with size 8 and string  
print (ran_gen(8, "AEIOSUMA23")) 

Perché avevo bisogno di solo 4-6 personaggi casuali invece di ingombranti GUID.


Questo sembra completamente estraneo alla domanda, che riguarda gli UUID.
sox con Monica il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.