Самый легкий способ создания случайной строки и случайного шестнадцатеричного числа
Каков наиболее легкий способ создания случайной строки из 30 символов, например:
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
И шестнадцатеричное число из 30 цифр, таких как following?
8c6f78ac23b4a7b8c0182d7a89e9b1
Ответы
Ответ 1
Я получил более быстрый для шестнадцатеричного вывода. Используя те же самые 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
делает только один вызов случайного модуля, не нужно строить или читать список, а затем делает остальные с форматированием строки.
Ответ 2
30-значная шестнадцатеричная строка:
>>> import os,binascii
>>> print binascii.b2a_hex(os.urandom(15))
"c84766ca4a3ce52c3602bbf02ad1f7"
Преимущество заключается в том, что это приводит к случайности непосредственно из ОС, что может быть более безопасным и/или быстрее, чем random(), и вам не нужно его посещать.
Ответ 3
В Py3. 6+ другой вариант - использовать новый стандартный модуль secrets
:
>>> import secrets
>>> secrets.token_hex(15)
'8d9bad5b43259c6ee27d9aadc7b832'
>>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable
'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
Ответ 4
import string
import random
lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)]
str = "".join(lst)
print str
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
Ответ 5
Драматически более быстрое решение, чем здесь:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits")
0.8056681156158447
Ответ 6
Примечание: random.choice(string.hexdigits)
неверно, потому что string.hexdigits
возвращает 0123456789abcdefABCDEF
(как в нижнем, так и в верхнем регистре), поэтому вы получите результат смещения, при этом шестнадцатеричная цифра "c" в два раза вероятнее появится в виде цифры ' 7'. Вместо этого просто используйте random.choice('0123456789abcdef')
.
Ответ 7
Другой метод:
from Crypto import Random
import binascii
my_hex_value = binascii.hexlify(Random.get_random_bytes(30))
Точка: значение байта всегда равно значению в hex.
Ответ 8
однострочная функция:
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)
Ответ 9
Кстати, это результат использования 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
Ответ 10
Там быстрее, чем указано в 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 (последний arg), чтобы изменить длину вывода на основе вашего требования. Итак, для 60 char one:
binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
Ответ 11
In [1]: import random
In [2]: hex(random.getrandbits(16))
Out[2]: '0x3b19'
Ответ 12
добавление еще одного ответа в микс, который работает быстрее, чем решение @eemz, а также полностью буквенно-цифровой. Обратите внимание, что это не дает шестнадцатеричного ответа.
import random
import string
LETTERS_AND_DIGITS = string.ascii_letters + string.digits
def random_choice_algo(width):
return ''.join(random.choice(LETTERS_AND_DIGITS) for i in range(width))
def random_choices_algo(width):
return ''.join(random.choices(LETTERS_AND_DIGITS, k=width))
print(generate_random_string(10))
# prints "48uTwINW1D"
быстрый тест производительности
from timeit import timeit
from functools import partial
arg_width = 10
print("random_choice_algo", timeit(partial(random_choice_algo, arg_width)))
# random_choice_algo 8.180561417000717
print("random_choices_algo", timeit(partial(random_choices_algo, arg_width)))
# random_choices_algo 3.172438014007639