Як створити GUID / UUID в Python


686

Як створити GUID в Python, який не залежить від платформи? Я чую, що існує метод, що використовує ActivePython для Windows, але це Windows тільки тому, що він використовує COM. Чи існує метод, що використовує звичайний Python?



34
Для любові до всього, що священне, це UUID - Universal Unique ID en.wikipedia.org/wiki/Universally_unique_identifier - його якраз те, що MS, на жаль, віддало перевагу GUID.
david.barkhuizen

5
Ось один для вас лайнер:python -c 'import uuid; print(uuid.uuid4())'
Ctrl-C

Відповіді:


776

Модуль uuid, в Python 2.5 і вище, забезпечує генерацію UUID, сумісну з RFC. Докладніше див. Документи модулів та RFC. [ джерело ]

Документи:

Приклад (працює над 2 та 3):

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

20
Також перегляньте shortuuidнаписаний нами модуль, оскільки він дозволяє генерувати більш короткі, читаються UUID: github.com/stochastic-technologies/shortuuid
Ставрос Корокітакіс

2
@StavrosKorokithakis: Ви випадково написали короткий модуль для Python 3.x?
Джей Патель

2
@JayPatel Чи shorttuuid не працює для Python 3? Якщо ні, подайте помилку.
Ставрос Корокітакіс

1
Яка різниця між uuid4().hexі str(uuid4())?
Кевін

6
Ну, як ви бачите вище, str(uuid4())повертає рядкове представлення UUID з включеними тире, в той час як uuid4().hexповертає "UUID як шістнадцятковий рядок 32 символу"
stuartd

324

Якщо ви використовуєте Python 2.5 або новішої версії, модуль uuid вже включений до стандартного розподілу Python.

Наприклад:

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

116

Скопійовано з: https://docs.python.org/2/library/uuid.html (Оскільки опубліковані посилання не були активними і вони постійно оновлюються)

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

Я використовую GUID як випадкові ключі для операцій з базою даних.

Шістнадцяткова форма, з тире та зайвими символами здається мені зайвою. Але мені також подобається, що рядки, що представляють шістнадцяткові числа, дуже безпечні тим, що не містять символів, які можуть спричинити проблеми в таких ситуаціях, як "+", '=' тощо.

Замість шістнадцяткових я використовую безпечний для URL-адрес рядок64. Наведене нижче не відповідає жодним специфікаціям UUID / GUID (крім необхідної кількості випадковості).

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
Якщо ви не збираєтеся заважати використовувати його в будь-якому контексті UUID, ви можете просто скористатися random.getrandbits(128).to_bytes(16, 'little')або (для криптовалюти) os.urandom(16)та отримати повне 128 біт випадкових випадків (UUIDv4 використовує 6-7 біт на інформацію про версію). Або використовуйте лише 15 байт (втрачаючи 1-2 біти випадкових та UUIDv4) і уникайте необхідності обрізати =знаки, одночасно зменшуючи розмір коду до 20 байт (з 24, обрізаний до 22), як будь-який кратний з 3 байт кодує до #bytes / 3 * 4базових64 символів, не вимагаючи прокладки.
ShadowRanger

@ShadowRanger Так, це в основному ідея. 128 випадкових бітів, максимально коротких, але також безпечних для URL-адрес. В ідеалі він використовував би лише великі і малі літери, а потім цифри. Тож я здогадуюсь, що рядок-62.
Кріс Датроу

Коли я використовую вашу функцію, я отримую помилку типу з returnтвердження, що очікує байтового об'єкта. Це можна зафіксувати за допомогою return str(r_uuid).replace('=','').
Позначити Кортинка

8

Якщо вам потрібно передати UUID для первинного ключа для вашої моделі або унікального поля, то нижче коду повертається об’єкт UUID -

 import uuid
 uuid.uuid4()

Якщо вам потрібно передати UUID як параметр для URL-адреси, ви можете зробити наступний код -

import uuid
str(uuid.uuid4())

Якщо ви хочете шістнадцяткове значення для UUID, ви можете зробити наступне -

import uuid    
uuid.uuid4().hex

0

Ця функція повністю настроюється і генерує унікальний uid на основі заданого формату

наприклад: [8, 4, 4, 4, 12], це згаданий формат, і він буде генерувати наступний 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 є стандартними, але не змінюються за довжиною. Генерування випадкових рядків, що настроюються, може бути корисним у деяких ситуаціях, але не в цьому контексті. Ви можете перевірити en.wikipedia.org/wiki/Universally_unique_identifier для визначення.
miguelr

2
Краще уникайте цього, або ви можете зіткнутися з проблемами сумісності (це не стандартні GUID)
Sylvain Gantois

-1

Відповідь 2019 року (для Windows):

Якщо потрібно постійний UUID, який однозначно ідентифікує машину в Windows, ви можете скористатися цим фокусом: (Скопійовано з моєї відповіді за адресою 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())

Використовує API Windows для отримання постійного UUID комп'ютера, потім обробляє рядок, щоб переконатися, що він є дійсним UUID, і нарешті повертає об’єкт Python ( https://docs.python.org/3/library/uuid.html ), що дає вам зручніше способи використання даних (наприклад, 128-розрядне ціле число, шістнадцятковий рядок тощо).

Удачі!

PS: Виклик підпроцесу, ймовірно, може бути замінений на типи, що безпосередньо викликають ядро ​​Windows / DLL. Але для моїх цілей ця функція - це все, що мені потрібно. Це робить сильну перевірку та дає правильні результати.


-1

Перевірте цю посаду, мені дуже допомогли. Словом, найкращим варіантом для мене був:

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

Тому що мені було потрібно всього 4-6 випадкових символів замість об'ємного GUID.


Це здається абсолютно не пов'язаним із питанням, що стосується UUID.
сокс з Монікою
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.