Самый легкий способ создать случайную строку и случайное шестнадцатеричное число - PullRequest
72 голосов
/ 06 мая 2010

Какой самый простой способ создать случайную строку из 30 символов, подобную следующей?

ufhy3skj5nca0d2dfh9hwd2tbk9sw1

А шестнадцатеричное число, состоящее из 30 цифр, вроде следующего?

8c6f78ac23b4a7b8c0182d7a89e9b1

Ответы [ 11 ]

105 голосов
/ 06 мая 2010

Я получил более быстрый для шестнадцатеричного вывода. Используя те же t1 и t2, что и выше:

>>> t1 = timeit.Timer("''.join(random.choice('0123456789abcdef') for n in xrange(30))", "import random")
>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii")
>>> t3 = timeit.Timer("'%030x' % random.randrange(16**30)", "import random")
>>> for t in t1, t2, t3:
...     t.timeit()
... 
28.165037870407104
9.0292739868164062
5.2836320400238037

t3 делает только один вызов случайного модуля, не должен создавать или читать список, а затем делает все остальное с форматированием строки.

67 голосов
/ 06 мая 2010

30-значная шестнадцатеричная строка:

>>> import os,binascii
>>> print binascii.b2a_hex(os.urandom(15))
"c84766ca4a3ce52c3602bbf02ad1f7"

Преимущество заключается в том, что он получает случайность непосредственно от ОС, которая может быть более безопасной и / или более быстрой, чем random (), и вам не нужно ее заполнять.

27 голосов
/ 05 апреля 2017

В Py3.6 + другой вариант - использовать новый стандартный модуль secrets:

>>> import secrets
>>> secrets.token_hex(15)
'8d9bad5b43259c6ee27d9aadc7b832'
>>> secrets.token_urlsafe(22)   # may include '_-' unclear if that is acceptable
'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
27 голосов
/ 06 мая 2010
import string
import random
lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)]
str = "".join(lst)
print str
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
24 голосов
/ 02 февраля 2016

Значительно более быстрое решение, чем здесь:

timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits")
0.8056681156158447
15 голосов
/ 17 марта 2013

Примечание: random.choice(string.hexdigits) неверно, потому что string.hexdigits возвращает 0123456789abcdefABCDEF (как строчные, так и прописные), поэтому вы получите смещенный результат, поскольку шестнадцатеричная цифра 'c' в два раза чаще появляется как цифра ' 7' . Вместо этого просто используйте random.choice('0123456789abcdef').

6 голосов
/ 17 октября 2016

Другой метод:

from Crypto import Random
import binascii

my_hex_value = binascii.hexlify(Random.get_random_bytes(30))

Дело в том: значение байта всегда равно значению в шестнадцатеричном формате .

5 голосов
/ 11 апреля 2015

однострочная функция:

import random
import string

def generate_random_key(length):
    return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(length))

print generate_random_key(30)
2 голосов
/ 08 июля 2013

Есть более быстрый вариант по сравнению с тем, что упомянул jcdyer. Это занимает ~ 50% его самого быстрого метода.

from numpy.random.mtrand import RandomState
import binascii
rand = RandomState()

lo = 1000000000000000
hi = 999999999999999999
binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:30]

>>> timeit.Timer("binascii.b2a_hex(rand.randint(lo,hi,2).tostring())[:30]", \
...                 'from __main__ import lo,hi,rand,binascii').timeit()
1.648831844329834         <-- this is on python 2.6.6
2.253110885620117         <-- this on python 2.7.5

Если вы хотите в base64:

binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]

Вы можете изменить параметр размера, передаваемый в randint (последний аргумент), чтобы изменить длину вывода в зависимости от ваших требований. Итак, для символа 60 символов:

binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
2 голосов
/ 06 мая 2010

Кстати, это результат использования timeit на двух предложенных подходах:

Использование random.choice():

>>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string")
>>> t1.timeit()
69.558588027954102

Использование binascii.b2a_hex():

>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii")
>>> t2.timeit()
16.288421154022217
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...