Jak utworzyć GUID / UUID w Pythonie


686

Jak utworzyć identyfikator GUID w języku Python, który jest niezależny od platformy? Słyszałem, że istnieje metoda wykorzystująca ActivePython w systemie Windows, ale jest to Windows tylko dlatego, że używa COM. Czy istnieje metoda wykorzystująca zwykły Python?



34
Z miłości do wszystkiego, co święte, jest to UUID - Universal Unique ID en.wikipedia.org/wiki/Universally_unique_identifier - po prostu niestety MS wybrało GUID.
david.barkhuizen

5
Oto jeden linijka dla ciebie:python -c 'import uuid; print(uuid.uuid4())'
Ctrl-C

Odpowiedzi:


776

Moduł uuid, w Pythonie 2.5 i nowszych, zapewnia generowanie UUID zgodnego z RFC. Szczegółowe informacje można znaleźć w dokumentacji modułu i dokumencie RFC. [ źródło ]

Dokumenty:

Przykład (praca na 2 i 3):

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

20
Zobacz także shortuuidmoduł, który napisałem, ponieważ pozwala on generować krótsze, czytelne identyfikatory UUID: github.com/stochastic-technologies/shortuuid
Stavros Korokithakis

2
@StavrosKorokithakis: czy przypadkiem napisałeś moduł shortuuid dla Pythona 3.x?
Jay Patel,

2
@JayPatel Czy shortuuid nie działa w Pythonie 3? Jeśli nie, zgłoś błąd.
Stavros Korokithakis

1
Jaka jest różnica między uuid4().hexi str(uuid4())?
Kevin

6
Cóż, jak widać powyżej, str(uuid4())zwraca ciąg reprezentujący UUID z dołączonymi myślnikami, podczas gdy uuid4().hexzwraca „UUID jako 32-znakowy ciąg szesnastkowy”
stuartd 30.01.2018

324

Jeśli używasz języka Python w wersji 2.5 lub nowszej, moduł uuid jest już dołączony do standardowej dystrybucji języka Python.

Dawny:

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

116

Skopiowano z: https://docs.python.org/2/library/uuid.html (Ponieważ opublikowane linki nie były aktywne i ciągle się aktualizują)

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

Używam GUID jako losowych kluczy do operacji typu bazy danych.

Forma szesnastkowa z myślnikami i dodatkowymi znakami wydaje mi się niepotrzebnie długa. Ale podoba mi się również to, że ciągi reprezentujące liczby szesnastkowe są bardzo bezpieczne, ponieważ nie zawierają znaków, które mogą powodować problemy w niektórych sytuacjach, takich jak „+”, „=” itp.

Zamiast szesnastkowego używam ciągu base64 bezpiecznego dla adresu URL. Poniższe informacje nie są jednak zgodne z żadną specyfikacją UUID / GUID (poza wymaganą losowością).

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
Jeśli nie zamierzasz zawracać sobie głowy używaniem go w kontekście UUID, możesz równie dobrze użyć random.getrandbits(128).to_bytes(16, 'little')lub (dla losowości kryptograficznej) os.urandom(16)i uzyskać pełne 128 bitów losowości (UUIDv4 używa 6-7 bitów w informacjach o wersji). Lub użyj tylko 15 bajtów (tracąc 1-2 bity losowe vs. UUIDv4) i unikaj potrzeby przycinania =znaków, jednocześnie zmniejszając rozmiar zakodowanego do 20 bajtów (z 24, przycinanych do 22), ponieważ dowolna wielokrotność 3 bajtów koduje do #bytes / 3 * 4base64 znaków bez wypełniania.
ShadowRanger

@ShadowRanger Tak, to w zasadzie pomysł. 128 losowych bitów, możliwie najkrótszych, jednocześnie bezpiecznych dla adresów URL. Idealnie byłoby używać tylko wielkich i małych liter, a następnie cyfr. Więc chyba ciąg 62-base.
Chris Dutrow

Kiedy używam twojej funkcji, pojawia się błąd typu z returninstrukcji oczekującej obiektu podobnego do bajtów. Można to naprawić za pomocą return str(r_uuid).replace('=','').
Mark Kortink

8

Jeśli musisz przekazać UUID dla klucza podstawowego dla swojego modelu lub unikalnego pola, poniższy kod zwraca obiekt UUID -

 import uuid
 uuid.uuid4()

Jeśli musisz podać UUID jako parametr adresu URL, możesz to zrobić jak poniżej kodu -

import uuid
str(uuid.uuid4())

Jeśli chcesz mieć wartość szesnastkową dla UUID, możesz wykonać poniższe -

import uuid    
uuid.uuid4().hex

0

Ta funkcja jest w pełni konfigurowalna i generuje unikalny identyfikator użytkownika na podstawie określonego formatu

np .: - [8, 4, 4, 4, 12], jest to wspomniany format i wygeneruje następujący identyfikator 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
UUID są standardowe i nie mają zmiennej długości. Generowanie losowego ciągu w konfigurowalny sposób może być użyteczny w niektórych sytuacjach, ale nie w tym kontekście. Możesz sprawdzić en.wikipedia.org/wiki/Universally_unique_identifier dla definicji.
miguelr

2
Lepiej unikać tego jednego lub może napotkasz problemy z kompatybilnością (nie są to standardowe GUID)
Sylvain GANTOIS

-1

Odpowiedź 2019 (dla Windows):

Jeśli chcesz mieć stały identyfikator UUID, który jednoznacznie identyfikuje maszynę w systemie Windows, możesz użyć tej sztuczki: (Skopiowano z mojej odpowiedzi na 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())

Używa interfejsu API systemu Windows, aby uzyskać stały identyfikator UUID komputera, a następnie przetwarza ciąg znaków, aby upewnić się, że jest to prawidłowy identyfikator UUID, i na koniec zwraca obiekt Python ( https://docs.python.org/3/library/uuid.html ), co daje ci wygodę sposoby wykorzystania danych (takie jak 128-bitowa liczba całkowita, ciąg szesnastkowy itp.).

Powodzenia!

PS: Wywołanie podprocesu można prawdopodobnie zastąpić ctypami bezpośrednio wywołującymi jądro systemu Windows / biblioteki DLL. Ale do moich celów ta funkcja jest wszystkim, czego potrzebuję. Dokonuje silnej walidacji i daje prawidłowe wyniki.


-1

Sprawdź ten post, bardzo mi pomógł. Krótko mówiąc, najlepszą opcją dla mnie było:

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

Ponieważ potrzebowałem tylko 4-6 losowych znaków zamiast obszernego GUID.


Wydaje się to całkowicie niezwiązane z pytaniem dotyczącym UUID.
sox z Monicą
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.