Ницца. Просто создайте случайное число длиной 30 шестнадцатеричных цифр и распечатайте его. Очевидно, когда указано. Хороший.
eemz 06
Интересно, что я как бы забыл, что Python (и модуль random) изначально обрабатывает bigints.
wump
3
См. Ответ yaronf ниже по использованию string.hexdigits: stackoverflow.com/a/15462293/311288 " string.hexdigitsвозвращает 0123456789abcdefABCDEF(как строчные, так и прописные), [...]. Вместо этого просто используйте random.choice('0123456789abcdef')".
Thomas
3
Используйте getrandbitsвместо, randrangeчтобы сделать это еще быстрее.
Робинст
@robinst подытожил. '%030x' % random.getrandbits(60)даже быстрее, чем '%030x' % random.randrange(16**30), вероятно, потому что ему не нужно выполнять какие-либо преобразования в / из больших групп
Преимущество состоит в том, что случайность получается прямо из ОС, что может быть более безопасно и / или быстрее, чем random (), и вам не нужно его заполнять.
это интересно и, вероятно, хороший выбор для генерации 30-значного шестнадцатеричного числа, которое он хочет. вероятно, можно было бы также использовать urandom и оператор среза для генерации буквенно-цифровой строки.
eemz 06
Я взглянул на другие функции в binascii, у них есть base64 и uuencode, но нет способа сгенерировать первый тип строк, который он хочет (base36).
wump
1
Достаточно ли этого случайного / уникального для использования, скажем, в токенах сеанса?
В Py3.6 + другой вариант - использовать новый стандартный secretsмодуль:
>>> import secrets
>>> secrets.token_hex(15)
'8d9bad5b43259c6ee27d9aadc7b832'>>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
import string
import random
lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)]
str = "".join(lst)
print str
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
Один пользователь должен попробовать все методы на одном компьютере, чтобы получить точную базовую линию. Технические характеристики оборудования могут иметь большое значение. >>>> timeit.timeit ("'% 0x'% getrandbits (30 * 4)", "из случайного импорта getrandbits") 0.2471246949999113 </pre>
ptay
Спасибо, это намного быстрее, чем другие выше. %timeit '%030x' % randrange(16**30)дает 1000000 циклов, лучшее из 3: 1,61 мкс на цикл, а %timeit '%0x' % getrandbits(30 * 4)дает 1000000 циклов, лучшее из 3: 396 нс на цикл
frmdstryr
15
Примечание: random.choice(string.hexdigits)неверно, потому что string.hexdigitsвозвращается 0123456789abcdefABCDEF(как в нижнем, так и в верхнем регистре), поэтому вы получите предвзятый результат, где шестнадцатеричная цифра «c» в два раза чаще появляется, чем цифра «7». Вместо этого просто используйте random.choice('0123456789abcdef').
import random
import string
defgenerate_random_key(length):return''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(length))
print generate_random_key(30)
Есть более быстрый по сравнению с тем, что упомянул 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.62.253110885620117 <-- this on python 2.7.5
Вы можете изменить параметр размера, переданный в randint (последний аргумент), чтобы изменить длину вывода в зависимости от ваших требований. Итак, для 60-символьного:
Небольшая вариация: binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]где N=30.
dan-man
@ dan-man Спасибо за этот дополнительный метод. Однако я считаю, что на это требуется как минимум в 5 раз больше времени. Вы это тоже замечаете?
Итан,
0
добавление еще одного ответа к смеси, который работает быстрее, чем решение @eemz, а также является полностью буквенно-цифровым. Обратите внимание, что это не дает вам шестнадцатеричного ответа.
import random
import string
LETTERS_AND_DIGITS = string.ascii_letters + string.digits
defrandom_choice_algo(width):return''.join(random.choice(LETTERS_AND_DIGITS) for i in range(width))
defrandom_choices_algo(width):return''.join(random.choices(LETTERS_AND_DIGITS, k=width))
print(generate_random_string(10))
# prints "48uTwINW1D"
Это, конечно, не самая легкая версия, но она случайна, и ее легко настроить по своему желанию:
import random
defgenerate(random_chars=12, alphabet="0123456789abcdef"):
r = random.SystemRandom()
return''.join([r.choice(alphabet) for i in range(random_chars)])
Ответы:
Я получил более быстрый для вывода в шестнадцатеричный формат. Используя те же 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
выполняет только один вызов случайного модуля, не должен создавать или читать список, а затем выполняет все остальное с форматированием строки.источник
string.hexdigits
: stackoverflow.com/a/15462293/311288 "string.hexdigits
возвращает0123456789abcdefABCDEF
(как строчные, так и прописные), [...]. Вместо этого просто используйтеrandom.choice('0123456789abcdef')
".getrandbits
вместо,randrange
чтобы сделать это еще быстрее.'%030x' % random.getrandbits(60)
даже быстрее, чем'%030x' % random.randrange(16**30)
, вероятно, потому что ему не нужно выполнять какие-либо преобразования в / из больших групп30-значная шестнадцатеричная строка:
>>> import os,binascii >>> print binascii.b2a_hex(os.urandom(15)) "c84766ca4a3ce52c3602bbf02ad1f7"
Преимущество состоит в том, что случайность получается прямо из ОС, что может быть более безопасно и / или быстрее, чем random (), и вам не нужно его заполнять.
источник
В Py3.6 + другой вариант - использовать новый стандартный
secrets
модуль:>>> import secrets >>> secrets.token_hex(15) '8d9bad5b43259c6ee27d9aadc7b832' >>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable 'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
источник
import string import random lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)] str = "".join(lst) print str ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
источник
random.SystemRandom().choice
Значительно более быстрое решение, чем здесь:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits") 0.8056681156158447
источник
%timeit '%030x' % randrange(16**30)
дает 1000000 циклов, лучшее из 3: 1,61 мкс на цикл, а%timeit '%0x' % getrandbits(30 * 4)
дает 1000000 циклов, лучшее из 3: 396 нс на циклПримечание:
random.choice(string.hexdigits)
неверно, потому чтоstring.hexdigits
возвращается0123456789abcdefABCDEF
(как в нижнем, так и в верхнем регистре), поэтому вы получите предвзятый результат, где шестнадцатеричная цифра «c» в два раза чаще появляется, чем цифра «7». Вместо этого просто используйтеrandom.choice('0123456789abcdef')
.источник
Другой метод:
from Crypto import Random import binascii my_hex_value = binascii.hexlify(Random.get_random_bytes(30))
Дело в том, что значение байта всегда равно значению в шестнадцатеричном формате .
источник
однострочная функция:
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)
источник
In [1]: import random In [2]: hex(random.getrandbits(16)) Out[2]: '0x3b19'
источник
Между прочим, это результат использования
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
источник
Есть более быстрый по сравнению с тем, что упомянул 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]
источник
binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]
гдеN=30
.добавление еще одного ответа к смеси, который работает быстрее, чем решение @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
источник
Это, конечно, не самая легкая версия, но она случайна, и ее легко настроить по своему желанию:
import random def generate(random_chars=12, alphabet="0123456789abcdef"): r = random.SystemRandom() return ''.join([r.choice(alphabet) for i in range(random_chars)])
источник