Como criar um GUID / UUID em Python


685

Como crio um GUID no Python que é independente da plataforma? Ouvi dizer que existe um método usando o ActivePython no Windows, mas é o Windows apenas porque ele usa COM. Existe um método usando Python simples?



34
Pelo amor de tudo o que é sagrado, é um UUID - Universal Unique ID en.wikipedia.org/wiki/Universally_unique_identifier - é que, infelizmente, a MS preferiu o GUID.
david.barkhuizen

5
Aqui está um exemplo para você:python -c 'import uuid; print(uuid.uuid4())'
Ctrl-C

Respostas:


776

O módulo uuid, no Python 2.5 e superior, fornece geração UUID compatível com RFC. Consulte a documentação do módulo e a RFC para obter detalhes. [ fonte ]

Documentos:

Exemplo (trabalhando em 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
Além disso, dê uma olhada no shortuuidmódulo que escrevi, pois permite gerar UUIDs mais curtos e legíveis: github.com/stochastic-technologies/shortuuid
Stavros Korokithakis 31/12/12

2
@StavrosKorokithakis: você escreveu o módulo shortuuid para Python 3.x por acaso?
Jay Patel

2
@JayPatel O shortuuid não funciona no Python 3? Caso contrário, registre um bug.
Stavros Korokithakis 22/08/16

1
Qual é a diferença entre uuid4().hexe str(uuid4())?
Kevin

6
Bem, como você pode ver acima, str(uuid4())retorna uma representação de string do UUID com os traços incluídos, enquanto uuid4().hexretorna "o UUID como uma string hexadecimal de 32 caracteres"
stuartd

324

Se você estiver usando o Python 2.5 ou posterior, o módulo uuid já está incluído na distribuição padrão do Python.

Ex:

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

116

Copiado de: https://docs.python.org/2/library/uuid.html (Como os links publicados não estavam ativos e continuam atualizando)

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

Eu uso GUIDs como chaves aleatórias para operações do tipo banco de dados.

A forma hexadecimal, com traços e caracteres extras, parece desnecessariamente longa para mim. Mas também gosto que cadeias de caracteres que representam números hexadecimais sejam muito seguras, pois não contêm caracteres que podem causar problemas em algumas situações, como '+', '=', etc.

Em vez de hexadecimal, eu uso uma string base64 segura para URL. O seguinte não está de acordo com nenhuma especificação UUID / GUID (exceto a quantidade necessária de aleatoriedade).

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 você não vai se incomodar em usá-lo em nenhum contexto de UUID, também poderá usar random.getrandbits(128).to_bytes(16, 'little')ou (para aleatoriedade de criptografia) os.urandom(16)e obter 128 bits aleatórios completos (o UUIDv4 usa 6-7 bits nas informações da versão). Ou use apenas 15 bytes (perdendo 1-2 bits aleatórios vs. UUIDv4) e evite a necessidade de cortar =sinais, reduzindo também o tamanho codificado para 20 bytes (de 24, aparado para 22), como qualquer múltiplo de 3 bytes codifica para #bytes / 3 * 4base64 caracteres sem preenchimento necessário.
ShadowRanger

@ShadowRanger Sim, isso é basicamente a ideia. 128 bits aleatórios, o mais curto possível, além de ser seguro para URL. Idealmente, usaria apenas letras maiúsculas e minúsculas e depois números. Então eu acho que uma string de base 62.
22419 Chris Dutrow

Quando uso sua função, recebo um erro de tipo da returninstrução que espera um objeto semelhante a bytes. Pode ser consertado com return str(r_uuid).replace('=','').
Mark Kortink 18/02

8

Se você precisar passar o UUID para uma chave primária para o seu modelo ou campo exclusivo, o código abaixo retornará o objeto UUID -

 import uuid
 uuid.uuid4()

Se você precisar passar o UUID como parâmetro para o URL, faça o seguinte abaixo do código -

import uuid
str(uuid.uuid4())

Se você quiser o valor hexadecimal para um UUID, faça o seguinte:

import uuid    
uuid.uuid4().hex

0

Esta função é totalmente configurável e gera um uid exclusivo com base no formato especificado

por exemplo: - [8, 4, 4, 4, 12], este é o formato mencionado e irá gerar o seguinte 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
Os UUIDs são padrão e não têm comprimento variável. Gerar uma sequência aleatória de forma configurável pode ser útil em algumas situações, mas não neste contexto. Você pode verificar en.wikipedia.org/wiki/Universally_unique_identifier para definição.
miguelr 29/01/19

2
Melhor evitar este ou você pode executar em problemas de compatibilidade (estes não são GUIDs padrão)
Sylvain Gantois

-1

Resposta 2019 (para Windows):

Se você deseja um UUID permanente que identifique uma máquina exclusivamente no Windows, use este truque: (Copiado da minha resposta em 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())

Usa a API do Windows para obter o UUID permanente do computador, depois processa a cadeia de caracteres para garantir que seja um UUID válido e, por fim, retorna um objeto Python ( https://docs.python.org/3/library/uuid.html ), que oferece uma conveniência maneiras de usar os dados (como número inteiro de 128 bits, sequência hexadecimal etc.).

Boa sorte!

PS: A chamada de subprocesso provavelmente poderia ser substituída por ctypes chamando diretamente o kernel / DLLs do Windows. Mas, para meus propósitos, essa função é tudo que preciso. Faz validação forte e produz resultados corretos.


-1

Confira este post, me ajudou muito. Em suma, a melhor opção para mim foi:

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 eu precisava de apenas 4-6 caracteres aleatórios em vez de GUID volumoso.


Isso parece completamente não relacionado à pergunta, que é sobre UUIDs.
sox com Monica
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.