Comment créer un GUID / UUID en Python


687

Comment créer un GUID en Python indépendant de la plateforme? J'entends qu'il y a une méthode utilisant ActivePython sur Windows mais c'est Windows uniquement parce qu'il utilise COM. Existe-t-il une méthode utilisant du Python ordinaire?



35
Pour l'amour de tout ce qui est sacré, c'est un UUID - Universal Unique ID en.wikipedia.org/wiki/Universally_unique_identifier - c'est juste que malheureusement MS a préféré le GUID.
david.barkhuizen

5
Voici une doublure pour vous:python -c 'import uuid; print(uuid.uuid4())'
Ctrl-C

Réponses:


777

Le module uuid, en Python 2.5 et supérieur, fournit une génération UUID compatible RFC. Voir la documentation du module et la RFC pour plus de détails. [ source ]

Documents:

Exemple (travail sur 2 et 3):

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

20
Jetez également un œil au shortuuidmodule que j'ai écrit, car il vous permet de générer des UUID plus courts et lisibles: github.com/stochastic-technologies/shortuuid
Stavros Korokithakis

2
@StavrosKorokithakis: avez-vous écrit un module shortuuid pour Python 3.x par hasard?
Jay Patel

2
@JayPatel Shortuuid ne fonctionne-t-il pas pour Python 3? Sinon, veuillez signaler un bogue.
Stavros Korokithakis

1
Quelle est la différence entre uuid4().hexet str(uuid4())?
Kevin

6
Eh bien, comme vous pouvez le voir ci-dessus, str(uuid4())renvoie une représentation sous forme de chaîne de l'UUID avec les tirets inclus, tandis que uuid4().hexrenvoie "L'UUID sous forme de chaîne hexadécimale à 32 caractères"
stuartd

324

Si vous utilisez Python 2.5 ou version ultérieure, le module uuid est déjà inclus avec la distribution standard Python.

Ex:

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

116

Copié à partir de: https://docs.python.org/2/library/uuid.html (puisque les liens publiés n'étaient pas actifs et qu'ils continuent de se mettre à jour)

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

J'utilise des GUID comme clés aléatoires pour les opérations de type base de données.

La forme hexadécimale, avec les tirets et les caractères supplémentaires me semble inutilement longue. Mais j'aime aussi que les chaînes représentant des nombres hexadécimaux soient très sûres car elles ne contiennent pas de caractères qui peuvent causer des problèmes dans certaines situations telles que '+', '=', etc.

Au lieu de hexadécimal, j'utilise une chaîne base64 sans danger pour les URL. Cependant, ce qui suit n'est conforme à aucune spécification UUID / GUID (à part le fait d'avoir la quantité d'aléatoire requise).

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
Si vous n'allez pas vous soucier de l'utiliser dans des contextes UUID, vous pouvez tout aussi bien utiliser random.getrandbits(128).to_bytes(16, 'little')ou (pour l'aléa cryptographique) os.urandom(16)et obtenir 128 bits aléatoires complets (UUIDv4 utilise 6-7 bits sur les informations de version). Ou utilisez seulement 15 octets (en perdant 1 à 2 bits aléatoires par rapport à UUIDv4) et évitez d'avoir à couper les =signes tout en réduisant la taille codée à 20 octets (de 24, découpés à 22), car tout multiple de 3 octets code en #bytes / 3 * 4caractères base64 sans remplissage requis.
ShadowRanger

@ ShadowRanger Oui, c'est essentiellement l'idée. 128 bits aléatoires, aussi courts que possible, tout en étant sûrs pour les URL. Idéalement, il n'utiliserait que des lettres majuscules et minuscules, puis des chiffres. Je suppose donc une chaîne de base 62.
Chris Dutrow

Lorsque j'utilise votre fonction, j'obtiens une erreur de type de la returndéclaration qui attend un objet de type octets. Il peut être corrigé avec return str(r_uuid).replace('=','').
Mark Kortink

8

Si vous devez transmettre l'UUID pour une clé primaire pour votre modèle ou champ unique, le code ci-dessous renvoie l'objet UUID -

 import uuid
 uuid.uuid4()

Si vous devez passer l'UUID comme paramètre pour l'URL, vous pouvez faire comme ci-dessous le code -

import uuid
str(uuid.uuid4())

Si vous voulez la valeur hexadécimale d'un UUID, vous pouvez faire celle ci-dessous -

import uuid    
uuid.uuid4().hex

0

Cette fonction est entièrement configurable et génère un UID unique basé sur le format spécifié

par exemple: - [8, 4, 4, 4, 12], c'est le format mentionné et il générera l'uuid suivant

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
Les UUID sont standard et ne varient pas en longueur. La génération d'une chaîne aléatoire d'une manière configurable peut être utile dans certaines situations, mais pas dans ce contexte. Vous pouvez vérifier en.wikipedia.org/wiki/Universally_unique_identifier pour la définition.
miguelr

2
Mieux vaut éviter celui-ci ou vous pourriez rencontrer des problèmes de compatibilité (ce ne sont pas des GUID standard)
Sylvain Gantois

-1

Réponse 2019 (pour Windows):

Si vous voulez un UUID permanent qui identifie une machine uniquement sous Windows, vous pouvez utiliser cette astuce: (Copié de ma réponse sur 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())

Utilise l'API Windows pour obtenir l'UUID permanent de l'ordinateur, puis traite la chaîne pour s'assurer qu'il s'agit d'un UUID valide et retourne enfin un objet Python ( https://docs.python.org/3/library/uuid.html ) qui vous offre une commodité façons d'utiliser les données (comme un entier de 128 bits, une chaîne hexadécimale, etc.).

Bonne chance!

PS: L'appel de sous-processus pourrait probablement être remplacé par des ctypes appelant directement le noyau / DLL Windows. Mais pour mes besoins, cette fonction est tout ce dont j'ai besoin. Il effectue une validation solide et produit des résultats corrects.


-1

Consultez ce post, m'a beaucoup aidé. En bref, la meilleure option pour moi était:

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

Parce que je n'avais besoin que de 4 à 6 caractères aléatoires au lieu d'un GUID volumineux.


Cela semble complètement sans rapport avec la question, qui concerne les UUID.
sox avec Monica le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.