Agradável. Basta gerar um número aleatório de 30 dígitos hexadecimais e imprimi-lo. Óbvio quando apontado. Agradável.
eemz
Interessante, eu meio que esqueci que Python (e o módulo aleatório) lida com bigints nativamente.
wump
3
Veja a resposta de yaronf abaixo sobre como usar string.hexdigits: stackoverflow.com/a/15462293/311288 " string.hexdigitsretorna 0123456789abcdefABCDEF(tanto em minúsculas quanto em maiúsculas), [...]. Em vez disso, apenas use random.choice('0123456789abcdef')."
Thomas
3
Use em getrandbitsvez de randrangepara torná-lo ainda mais rápido.
robinst
@robinst tem um bom argumento. '%030x' % random.getrandbits(60)é ainda mais rápido do que '%030x' % random.randrange(16**30), provavelmente porque não precisa fazer nenhuma conversão de / para big-ints
A vantagem é que ele obtém aleatoriedade diretamente do sistema operacional, que pode ser mais seguro e / ou mais rápido do que random (), e você não precisa gerá-lo.
isso é interessante e provavelmente uma boa escolha para gerar o número hexadecimal de 30 dígitos que ele deseja. provavelmente poderia usar urandom e um operador de fatia para gerar a string alfanumérica também.
eemz
Eu dei uma olhada nas outras funções em binascii, elas têm base64 e uuencode, mas nenhuma maneira de gerar o primeiro tipo de string que ele quer (base36).
wump
1
Isso é aleatório / exclusivo o suficiente para ser usado em, digamos, tokens de sessão?
No Py3.6 +, outra opção é usar o novo secretsmódulo padrão :
>>> 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)
printstr
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
Um usuário deve tentar todos os métodos na mesma máquina para obter uma linha de base precisa. As especificações de hardware podem fazer uma grande diferença. >>>> timeit.timeit ("'% 0x'% getrandbits (30 * 4)", "de importação aleatória getrandbits") 0,2471246949999113 </pre>
ptay
Obrigado, isso muito mais rápido do que os outros acima. %timeit '%030x' % randrange(16**30)dá 1.000.000 de loops, melhor de 3: 1,61 µs por loop, enquanto %timeit '%0x' % getrandbits(30 * 4)dá 1.000.000 de loops, melhor de 3: 396 ns por loop
frmdstryr
15
Nota: random.choice(string.hexdigits)está incorreto, porque string.hexdigitsretorna 0123456789abcdefABCDEF(tanto em minúsculas quanto em maiúsculas), então você obterá um resultado tendencioso, com o dígito hex 'c' duas vezes mais provável de aparecer do que o dígito '7'. Em vez disso, basta usar random.choice('0123456789abcdef').
Existe um mais rápido em comparação com o que jcdyer mencionou. Isso leva cerca de 50% de seu método mais rápido.
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
Você pode alterar o parâmetro de tamanho passado para randint (último argumento) para variar o comprimento de saída com base em seus requisitos. Então, para um de 60 caracteres:
Uma ligeira variação: binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]onde N=30.
dan-man
@ dan-man Obrigado por este método opcional. No entanto, acho que ele consome pelo menos 5 vezes mais tempo. Você percebe isso também?
Ethan
0
adicionando mais uma resposta à combinação que tem um desempenho mais rápido do que a solução @eemz e também é totalmente alfanumérica. Observe que isso não fornece uma resposta hexadecimal.
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 inrange(width))
defrandom_choices_algo(width):return''.join(random.choices(LETTERS_AND_DIGITS, k=width))
print(generate_random_string(10))
# prints "48uTwINW1D"
Esta certamente não é a versão mais leve, mas é aleatória e é fácil de ajustar o alfabeto / comprimento que você deseja:
import random
defgenerate(random_chars=12, alphabet="0123456789abcdef"):
r = random.SystemRandom()
return''.join([r.choice(alphabet) for i inrange(random_chars)])
Respostas:
Eu tenho um mais rápido para a saída hexadecimal. Usando o mesmo t1 e t2 acima:
>>> 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
faz apenas uma chamada para o módulo aleatório, não tem que construir ou ler uma lista e então faz o resto com formatação de string.fonte
string.hexdigits
: stackoverflow.com/a/15462293/311288 "string.hexdigits
retorna0123456789abcdefABCDEF
(tanto em minúsculas quanto em maiúsculas), [...]. Em vez disso, apenas userandom.choice('0123456789abcdef')
."getrandbits
vez derandrange
para torná-lo ainda mais rápido.'%030x' % random.getrandbits(60)
é ainda mais rápido do que'%030x' % random.randrange(16**30)
, provavelmente porque não precisa fazer nenhuma conversão de / para big-intsString hexadecimal de 30 dígitos:
>>> import os,binascii >>> print binascii.b2a_hex(os.urandom(15)) "c84766ca4a3ce52c3602bbf02ad1f7"
A vantagem é que ele obtém aleatoriedade diretamente do sistema operacional, que pode ser mais seguro e / ou mais rápido do que random (), e você não precisa gerá-lo.
fonte
No Py3.6 +, outra opção é usar o novo
secrets
módulo padrão :>>> import secrets >>> secrets.token_hex(15) '8d9bad5b43259c6ee27d9aadc7b832' >>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable 'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
fonte
import string import random lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)] str = "".join(lst) print str ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
fonte
random.SystemRandom().choice
Solução dramaticamente mais rápida do que as aqui:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits") 0.8056681156158447
fonte
%timeit '%030x' % randrange(16**30)
dá 1.000.000 de loops, melhor de 3: 1,61 µs por loop, enquanto%timeit '%0x' % getrandbits(30 * 4)
dá 1.000.000 de loops, melhor de 3: 396 ns por loopNota:
random.choice(string.hexdigits)
está incorreto, porquestring.hexdigits
retorna0123456789abcdefABCDEF
(tanto em minúsculas quanto em maiúsculas), então você obterá um resultado tendencioso, com o dígito hex 'c' duas vezes mais provável de aparecer do que o dígito '7'. Em vez disso, basta usarrandom.choice('0123456789abcdef')
.fonte
Outro Método:
from Crypto import Random import binascii my_hex_value = binascii.hexlify(Random.get_random_bytes(30))
O ponto é: o valor do byte é sempre igual ao valor em hexadecimal .
fonte
função de uma linha:
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)
fonte
In [1]: import random In [2]: hex(random.getrandbits(16)) Out[2]: '0x3b19'
fonte
A propósito, este é o resultado do uso
timeit
das duas abordagens que foram sugeridas:Usando
random.choice()
:>>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string") >>> t1.timeit() 69.558588027954102
Usando
binascii.b2a_hex()
:>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii") >>> t2.timeit() 16.288421154022217
fonte
Existe um mais rápido em comparação com o que jcdyer mencionou. Isso leva cerca de 50% de seu método mais rápido.
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
Se você quiser em base64:
binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]
Você pode alterar o parâmetro de tamanho passado para randint (último argumento) para variar o comprimento de saída com base em seus requisitos. Então, para um de 60 caracteres:
binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
fonte
binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]
ondeN=30
.adicionando mais uma resposta à combinação que tem um desempenho mais rápido do que a solução @eemz e também é totalmente alfanumérica. Observe que isso não fornece uma resposta hexadecimal.
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"
um rápido benchmark rende
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
fonte
Esta certamente não é a versão mais leve, mas é aleatória e é fácil de ajustar o alfabeto / comprimento que você deseja:
import random def generate(random_chars=12, alphabet="0123456789abcdef"): r = random.SystemRandom() return ''.join([r.choice(alphabet) for i in range(random_chars)])
fonte