uuid — Identificadores universalmente únicos¶
Propósito: | El módulo uuid implementa identificadores universalmente únicos
como se describe en el RFC 4122. |
---|
RFC 4122 define un sistema para crear identificadores universalmente únicos de recursos de una manera que no requiere un registro central. Los valores UUID tienen una longitud de 128 bits y, como guía de referencia dice, «puede garantizar la singularidad a través del espacio y el tiempo». Son útiles para generar identificadores para documentos, hosts, aplicaciones clientes, y otras situaciones donde se necesita un valor único. El RFC se centra específicamente en crear un espacio de nombres de recurso uniforme de nombres y cubre tres algoritmos principales:
- Uso de direcciones MAC IEEE 802 como fuente de singularidad
- Uso de números pseudoaleatorios
- Uso de cadenas conocidas combinadas con hashing criptográfico
En todos los casos, el valor semilla se combina con el reloj del sistema y un valor de secuencia de reloj utilizado para mantener la singularidad en caso de que el reloj sea establecido hacia atrás.
UUID 1 - Direcciones MAC IEEE 802¶
Los valores de UUID versión 1 se calculan utilizando la dirección MAC del host.
El módulo uuid
usa getnode()
para obtener el valor MAC del sistema
actual.
import uuid
print(hex(uuid.getnode()))
Si un sistema tiene más de una tarjeta de red, y por lo tanto más de una MAC, cualquiera de los valores puede ser devuelto.
$ python3 uuid_getnode.py
0xa860b60304d5
Para generar un UUID para un host, identificado por su dirección MAC, use el
función uuid1()
. El argumento del identificador de nodo es opcional; deja
el campo en blanco para usar el valor devuelto por getnode()
.
import uuid
u = uuid.uuid1()
print(u)
print(type(u))
print('bytes :', repr(u.bytes))
print('hex :', u.hex)
print('int :', u.int)
print('urn :', u.urn)
print('variant :', u.variant)
print('version :', u.version)
print('fields :', u.fields)
print(' time_low : ', u.time_low)
print(' time_mid : ', u.time_mid)
print(' time_hi_version : ', u.time_hi_version)
print(' clock_seq_hi_variant: ', u.clock_seq_hi_variant)
print(' clock_seq_low : ', u.clock_seq_low)
print(' node : ', u.node)
print(' time : ', u.time)
print(' clock_seq : ', u.clock_seq)
Se puede acceder a los componentes del objeto UUID devuelto a través de
atributos de instancia de sólo lectura. Algunos atributos, como hex
,
int
, y urn
, son diferentes representaciones del valor UUID.
$ python3 uuid_uuid1.py
38332b62-2aea-11e8-b103-a860b60304d5
<class 'uuid.UUID'>
bytes : b'83+b*\xea\x11\xe8\xb1\x03\xa8`\xb6\x03\x04\xd5'
hex : 38332b622aea11e8b103a860b60304d5
int : 74702454824994792138317938288475964629
urn : urn:uuid:38332b62-2aea-11e8-b103-a860b60304d5
variant : specified in RFC 4122
version : 1
fields : (942877538, 10986, 4584, 177, 3, 185133323977941)
time_low : 942877538
time_mid : 10986
time_hi_version : 4584
clock_seq_hi_variant: 177
clock_seq_low : 3
node : 185133323977941
time : 137406974088391522
clock_seq : 12547
Debido al componente de tiempo, cada llamada a uuid1()
devuelve un nuevo
valor.
import uuid
for i in range(3):
print(uuid.uuid1())
En esta salida, solo el componente de tiempo (al comienzo de la cadena) cambia.
$ python3 uuid_uuid1_repeat.py
3842ca28-2aea-11e8-8fec-a860b60304d5
3844cd18-2aea-11e8-aca3-a860b60304d5
3844cdf4-2aea-11e8-ac38-a860b60304d5
Debido a que cada computadora tiene una dirección MAC diferente, la ejecución del programa de muestra en diferentes sistemas producirá valores completamente diferentes. Este ejemplo pasa IDs de nodo explícitos para simular la ejecución en diferentes hosts.
import uuid
for node in [0x1ec200d9e0, 0x1e5274040e]:
print(uuid.uuid1(node), hex(node))
Además de un valor de tiempo diferente, el identificador de nodo al final del UUID también cambia.
$ python3 uuid_uuid1_othermac.py
3851ea50-2aea-11e8-936d-001ec200d9e0 0x1ec200d9e0
3852caa6-2aea-11e8-a805-001e5274040e 0x1e5274040e
UUID 3 and 5 - Valores basados en nombres¶
También es útil en algunos contextos crear valores UUID a partir de nombres en lugar de valores aleatorios o basados en el tiempo. Versiones 3 y 5 de la especificación de UUID utilizan valores hash criptográficos (MD5 o SHA-1, respectivamente) para combinar valores semilla específicos del espacio de nombres con nombres. Hay varios espacios de nombres conocidos, identificados por valores UUID predefinidos, para trabajar con DNS, URL, OIDs ISO y nombres distinguidos X.500. Los nuevos espacios de nombres específicos de la aplicación pueden ser definidos generando y guardando valores UUID.
import uuid
hostnames = ['www.doughellmann.com', 'blog.doughellmann.com']
for name in hostnames:
print(name)
print(' MD5 :', uuid.uuid3(uuid.NAMESPACE_DNS, name))
print(' SHA-1 :', uuid.uuid5(uuid.NAMESPACE_DNS, name))
print()
Para crear un UUID a partir de un nombre DNS, pasa uuid.NAMESPACE_DNS
como
el argumento del espacio de nombres a uuid3()
o uuid5()
:
$ python3 uuid_uuid3_uuid5.py
www.doughellmann.com
MD5 : bcd02e22-68f0-3046-a512-327cca9def8f
SHA-1 : e3329b12-30b7-57c4-8117-c2cd34a87ce9
blog.doughellmann.com
MD5 : 9bdabfce-dfd6-37ab-8a3f-7f7293bcf111
SHA-1 : fa829736-7ef8-5239-9906-b4775a5abacb
El valor UUID para un nombre dado en un espacio de nombres es siempre el mismo, no importa cuándo o dónde se calcula.
import uuid
namespace_types = sorted(
n
for n in dir(uuid)
if n.startswith('NAMESPACE_')
)
name = 'www.doughellmann.com'
for namespace_type in namespace_types:
print(namespace_type)
namespace_uuid = getattr(uuid, namespace_type)
print(' ', uuid.uuid3(namespace_uuid, name))
print(' ', uuid.uuid3(namespace_uuid, name))
print()
Los valores para el mismo nombre en los espacios de nombres son diferentes.
$ python3 uuid_uuid3_repeat.py
NAMESPACE_DNS
bcd02e22-68f0-3046-a512-327cca9def8f
bcd02e22-68f0-3046-a512-327cca9def8f
NAMESPACE_OID
e7043ac1-4382-3c45-8271-d5c083e41723
e7043ac1-4382-3c45-8271-d5c083e41723
NAMESPACE_URL
5d0fdaa9-eafd-365e-b4d7-652500dd1208
5d0fdaa9-eafd-365e-b4d7-652500dd1208
NAMESPACE_X500
4a54d6e7-ce68-37fb-b0ba-09acc87cabb7
4a54d6e7-ce68-37fb-b0ba-09acc87cabb7
UUID 4 - Valores aleatorios¶
A veces, los valores UUID basados en el host y en el espacio de nombres no son
«lo suficientemente diferente». Por ejemplo, en los casos en que UUID está
destinado a ser utilizado como una clave hash, una secuencia más aleatoria de
valores con más diferenciación es deseable para evitar colisiones en la tabla
de hashs. Tener valores con menos dígitos comunes también hace que sea más
fácil encontrarlos en los archivos de registro. Para agregar una mayor
diferenciación en UUIDs, usa uuid4()
para generarlos usando valores de
entrada aleatorios.
import uuid
for i in range(3):
print(uuid.uuid4())
La fuente de aleatoriedad depende de qué bibliotecas de C están disponibles
cuando se importa uuid
. Si libuuid
(o uuid.dll
) puede ser cargada
y contiene una función para generar valores aleatorios, es usada. De lo
contrario, os.urandom()
o el módulo random
son usados.
$ python3 uuid_uuid4.py
74695723-65ed-4170-af77-b9f22608535d
db199e25-e292-41cd-b488-80a8f99d163a
196750b3-bbb9-488e-b3ec-62ec0e468bbc
Trabajar con objetos UUID¶
Además de generar nuevos valores UUID, es posible analizar cadenas en formatos estándar para crear objetos UUID, haciendo más fácil el manejo de comparaciones y operaciones de clasificación.
import uuid
def show(msg, l):
print(msg)
for v in l:
print(' ', v)
print()
input_values = [
'urn:uuid:f2f84497-b3bf-493a-bba9-7c68e6def80b',
'{417a5ebb-01f7-4ed5-aeac-3d56cd5037b0}',
'2115773a-5bf1-11dd-ab48-001ec200d9e0',
]
show('input_values', input_values)
uuids = [uuid.UUID(s) for s in input_values]
show('converted to uuids', uuids)
uuids.sort()
show('sorted', uuids)
Las llaves que la rodean se eliminan de la entrada, al igual que los guiones
(-
). Si la cadena tiene un prefijo que contiene urn:
y/o uuid:
,
también se elimina. El texto restante debe ser una cadena de 16 dígitos
hexadecimales, que luego se interpretan como un valor UUID.
$ python3 uuid_uuid_objects.py
input_values
urn:uuid:f2f84497-b3bf-493a-bba9-7c68e6def80b
{417a5ebb-01f7-4ed5-aeac-3d56cd5037b0}
2115773a-5bf1-11dd-ab48-001ec200d9e0
converted to uuids
f2f84497-b3bf-493a-bba9-7c68e6def80b
417a5ebb-01f7-4ed5-aeac-3d56cd5037b0
2115773a-5bf1-11dd-ab48-001ec200d9e0
sorted
2115773a-5bf1-11dd-ab48-001ec200d9e0
417a5ebb-01f7-4ed5-aeac-3d56cd5037b0
f2f84497-b3bf-493a-bba9-7c68e6def80b
Ver también
- Documentación de la biblioteca estándar para uuid
- Notas para portar Python 2 a 3 para uuid
- RFC 4122 – Un espacio de nombres de indentidicadores universalmente únicos (UUID) URN