Cómo crear un GUID / UUID en Python

686

¿Cómo creo un GUID en Python que sea independiente de la plataforma? Escuché que hay un método que usa ActivePython en Windows, pero es Windows solo porque usa COM. ¿Hay algún método que use Python simple?

Jonathon Watney
fuente
34
Por amor a todo lo que es sagrado, es un UUID - Universal Unique ID en.wikipedia.org/wiki/Universally_unique_identifier - es que desafortunadamente MS ha preferido GUID.
david.barkhuizen
55
Aquí hay un revestimiento para usted:python -c 'import uuid; print(uuid.uuid4())'
Ctrl-C

Respuestas:

776

El módulo uuid, en Python 2.5 y superior, proporciona generación de UUID compatible con RFC. Vea los documentos del módulo y el RFC para más detalles. [ fuente ]

Documentos:

Ejemplo (trabajando en 2 y 3):

>>> import uuid
>>> uuid.uuid4()
UUID('bd65600d-8669-4903-8a14-af88203add38')
>>> str(uuid.uuid4())
'f50ec0b7-f960-400d-91f0-c42a6d44e3d0'
>>> uuid.uuid4().hex
'9fe2c4e93f654fdbb24c02b15259716c'
Stuartd
fuente
20
Además, eche un vistazo al shortuuidmódulo que escribí, ya que le permite generar UUID más cortos y legibles: github.com/stochastic-technologies/shortuuid
Stavros Korokithakis
2
@StavrosKorokithakis: ¿ha escrito por casualidad el módulo shortuuid para Python 3.x?
Jay Patel
2
@JayPatel ¿Shortuuid no funciona para Python 3? De lo contrario, presente un error.
Stavros Korokithakis
1
¿Cuál es la diferencia entre uuid4().hexy str(uuid4())?
Kevin
66
Bueno, como puede ver arriba, str(uuid4())devuelve una representación de cadena del UUID con los guiones incluidos, mientras que uuid4().hexdevuelve "El UUID como una cadena hexadecimal de 32 caracteres"
stuartd
324

Si está utilizando Python 2.5 o posterior, el módulo uuid ya está incluido con la distribución estándar de Python.

Ex:

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

Copiado de: https://docs.python.org/2/library/uuid.html (Dado que los enlaces publicados no estaban activos y se siguen actualizando)

>>> 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')
Balaji Boggaram Ramanarayan
fuente
28

Utilizo GUID como claves aleatorias para operaciones de tipo de base de datos.

La forma hexadecimal, con guiones y caracteres adicionales me parece innecesariamente larga. Pero también me gusta que las cadenas que representan números hexadecimales sean muy seguras ya que no contienen caracteres que puedan causar problemas en algunas situaciones como '+', '=', etc.

En lugar de hexadecimal, uso una cadena base64 segura de url. Sin embargo, lo siguiente no se ajusta a ninguna especificación UUID / GUID (aparte de tener la cantidad de aleatoriedad requerida).

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('=', '')
Chris Dutrow
fuente
2
Si no va a molestarse en usarlo en ningún contexto de UUID, también puede usar random.getrandbits(128).to_bytes(16, 'little')o (para aleatorización criptográfica) os.urandom(16)y obtener 128 bits aleatorios completos (UUIDv4 usa 6-7 bits en la información de la versión). O use solo 15 bytes (perdiendo 1-2 bits de aleatorio frente a UUIDv4) y evite la necesidad de recortar =signos al tiempo que reduce el tamaño codificado a 20 bytes (de 24, recortado a 22), ya que cualquier múltiplo de 3 bytes codifica para #bytes / 3 * 4base64 caracteres sin necesidad de relleno.
ShadowRanger
@ShadowRanger Sí, esa es básicamente la idea. 128 bits aleatorios, tan cortos como sea convenientemente posible, a la vez que son seguros para URL. Idealmente, solo usaría letras mayúsculas y minúsculas y luego números. Así que supongo que una cadena de base 62.
Chris Dutrow
Cuando uso su función, recibo un error de tipo de la returndeclaración que espera un objeto similar a bytes. Se puede arreglar con return str(r_uuid).replace('=','').
Mark Kortink
8

Si necesita pasar UUID para una clave primaria para su modelo o campo único, el siguiente código devuelve el objeto UUID:

 import uuid
 uuid.uuid4()

Si necesita pasar UUID como parámetro para URL, puede hacer lo siguiente:

import uuid
str(uuid.uuid4())

Si desea el valor hexadecimal para un UUID, puede hacer el siguiente:

import uuid    
uuid.uuid4().hex
Mobasshir Bhuiyan
fuente
0

Esta función es totalmente configurable y genera un uid único basado en el formato especificado

por ejemplo: - [8, 4, 4, 4, 12], este es el formato mencionado y generará el siguiente 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
Manoj Selvin
fuente
3
Los UUID son estándar y no varían en longitud. Generar una cadena aleatoria de forma configurable puede ser útil en algunas situaciones, pero no en este contexto. Puede consultar en.wikipedia.org/wiki/Universally_unique_identifier para la definición.
miguelr
2
Mejor evite este o podría tener problemas de compatibilidad (estos no son GUID estándar)
Sylvain Gantois
-1

Respuesta 2019 (para Windows):

Si desea un UUID permanente que identifique una máquina exclusivamente en Windows, puede usar este truco: (Copiado de mi respuesta en 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())

Utiliza la API de Windows para obtener el UUID permanente de la computadora, luego procesa la cadena para asegurarse de que sea un UUID válido y, por último, devuelve un objeto Python ( https://docs.python.org/3/library/uuid.html ) que le brinda la comodidad formas de usar los datos (como un entero de 128 bits, una cadena hexadecimal, etc.).

¡Buena suerte!

PD: La llamada de subproceso probablemente podría reemplazarse con ctypes que llamen directamente al kernel de Windows / DLL. Pero para mis propósitos, esta función es todo lo que necesito. Hace una validación fuerte y produce resultados correctos.

Mitch McMabers
fuente
-1

Cheque esta publicación, me ayudó mucho. En resumen, la mejor opción para mí fue:

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

Porque necesitaba solo 4-6 caracteres aleatorios en lugar de un GUID voluminoso.

QtRoS
fuente
Esto parece no estar relacionado con la pregunta, que trata sobre UUID.
Medias con Mónica