Эффективно сгенерировать 16-символьную буквенно-цифровую строку - PullRequest
48 голосов
/ 24 марта 2010

Я ищу очень быстрый способ создания буквенно-цифрового уникального идентификатора для первичного ключа в таблице.

Хотелось бы что-нибудь подобное?

def genKey():
    hash = hashlib.md5(RANDOM_NUMBER).digest().encode("base64")
    alnum_hash = re.sub(r'[^a-zA-Z0-9]', "", hash)
    return alnum_hash[:16]

Какой будет хороший способ генерировать случайные числа? Если я основываю его на microtime, я должен учитывать возможность нескольких вызовов genKey () одновременно из разных экземпляров.

Или есть лучший способ сделать все это?

Ответы [ 9 ]

71 голосов
/ 11 июня 2015

Поскольку ни один из ответов не дает вам случайную строку, состоящую из символов 0-9, a-z, A-Z: вот рабочее решение, которое даст вам ок. 4.5231285e + 74 клавиши:

import random, string
x = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(16))
print(x)

Он также очень хорошо читается, не зная наизусть коды ASCII.

Существует еще более короткая версия, начиная с python 3.6.2:

import random, string
x = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
print(x)
46 голосов
/ 24 марта 2010

Вы можете использовать это:

>>> import random
>>> ''.join(random.choice('0123456789ABCDEF') for i in range(16))
'E2C6B2E19E4A7777'

Нет гарантии, что сгенерированные ключи будут уникальными, поэтому вы должны быть готовы повторить попытку с новым ключом в случае сбоя при первоначальной вставке. Кроме того, вы можете рассмотреть возможность использования детерминированного алгоритма для генерации строки из автоматически увеличенного идентификатора вместо использования случайных значений, поскольку это гарантирует вам уникальность (но также даст предсказуемые ключи).

32 голосов
/ 24 марта 2010

Посмотрите на модуль uuid (Python 2.5 +).

Быстрый пример:

>>> import uuid
>>> uid = uuid.uuid4()
>>> uid.hex
'df008b2e24f947b1b873c94d8a3f2201'

Обратите внимание, что OP запросил 16-символьную буквенно-цифровую строку, но строки UUID4 имеют длину 32 символа. Вы не должны усекать эту строку, вместо этого используйте полные 32 символа.

6 голосов
/ 29 сентября 2010

Для случайных чисел хорошим источником является os.urandom:

 >> import os
 >> import hashlib
 >> random_data = os.urandom(128)
 >> hashlib.md5(random_data).hexdigest()[:16]
4 голосов
/ 09 марта 2015
>>> import random
>>> ''.join(random.sample(map(chr, range(48, 57) + range(65, 90) + range(97, 122)), 16))
'CDh0geq3NpKtcXfP'
2 голосов
/ 25 марта 2010

Это значение увеличивается на 1 при каждом вызове (оно оборачивается). Решение о том, где лучше всего хранить значение, будет зависеть от того, как вы его используете. Вы можете найти это объяснение интереса, так как в нем обсуждается не только то, как работает Guids, но и как сделать меньшее.

Краткий ответ: Используйте некоторые из этих символов в качестве метки времени, а другие символы в качестве «юниксификатора», значение увеличивается на 1 при каждом обращении к генератору uid.

1 голос
/ 17 марта 2019

В Python 3.6, выпущенном в декабре 2016 года, был представлен модуль secrets.

Теперь вы можете сгенерировать случайный токен следующим образом:

import secrets

secrets.token_hex(16)

Из документов Python:

Модуль secrets используется для генерации криптографически стойких случайные числа, подходящие для управления данными, такими как пароли, учетная запись аутентификация, токены безопасности и связанные секреты.

В частности, secrets следует использовать вместо предпочтения по умолчанию генератор псевдослучайных чисел в модуле random, который предназначен для моделирования и симуляции, а не безопасности или криптографии.

https://docs.python.org/3/library/secrets.html

0 голосов
/ 02 августа 2017

просто используйте встроенный Python uuid :

import uuid
print uuid.uuid4().hex[:16].upper()
0 голосов
/ 24 апреля 2014

Просто используйте встроенный в Python uuid:

Если для ваших целей все в порядке, используйте встроенный пакет uuid .

Решение One Line:

>>> import uuid
>>> str(uuid.uuid4().get_hex().upper()[0:16])
'40003A9B8C3045CA'
...