Agradable. Simplemente genere un número aleatorio de 30 dígitos hexadecimales e imprímalo. Obvio cuando se señala. Buena esa.
eemz
Interesante, me olvidé de que Python (y el módulo aleatorio) maneja bigints de forma nativa.
wump
3
Vea la respuesta de yaronf a continuación sobre el uso string.hexdigits: stackoverflow.com/a/15462293/311288 " string.hexdigitsdevuelve 0123456789abcdefABCDEF(tanto en minúsculas como en mayúsculas), [...]. En su lugar, solo use random.choice('0123456789abcdef')".
Thomas
3
Úselo en getrandbitslugar de randrangepara hacerlo aún más rápido.
Robinst
@robinst tiene un buen punto. '%030x' % random.getrandbits(60)es incluso más rápido que '%030x' % random.randrange(16**30), probablemente porque no tiene que hacer ninguna conversión hacia / desde grandes empresas
La ventaja es que obtiene la aleatoriedad directamente del sistema operativo, que puede ser más seguro y / o más rápido que random (), y no es necesario que lo sembre.
eso es interesante y probablemente una buena opción para generar el número hexadecimal de 30 dígitos que desea. probablemente podría usar urandom y un operador de corte para generar también la cadena alfanumérica.
eemz
Eché un vistazo a las otras funciones en binascii, tienen base64 y uuencode, pero no hay forma de generar el primer tipo de cadenas que él quiere (base36).
wump
1
¿Es esto lo suficientemente aleatorio / único para usarse en, digamos, tokens de sesión?
En Py3.6 +, otra opción es usar el nuevo secretsmódulo estándar :
>>> 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
Un usuario tiene que probar todos los métodos en la misma máquina para obtener una línea de base precisa. Las especificaciones de hardware pueden marcar una gran diferencia. >>>> timeit.timeit ("'% 0x'% getrandbits (30 * 4)", "de importación aleatoria getrandbits") 0.2471246949999113 </pre>
ptay el
Gracias, esto es mucho más rápido que los otros anteriores. %timeit '%030x' % randrange(16**30)da 1000000 bucles, el mejor de 3: 1,61 µs por bucle mientras que %timeit '%0x' % getrandbits(30 * 4)da 1000000 bucles, el mejor de 3: 396 ns por bucle
frmdstryr
15
Nota: random.choice(string.hexdigits)es incorrecto, porque string.hexdigitsdevuelve 0123456789abcdefABCDEF(tanto en minúsculas como en mayúsculas), por lo que obtendrá un resultado sesgado, con el dígito hexadecimal 'c' el doble de probabilidades de aparecer que el dígito '7'. En su lugar, solo use 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)
Hay uno más rápido en comparación con lo que ha mencionado jcdyer. Esto requiere ~ 50% de su método más 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
Puede cambiar el parámetro de tamaño pasado a randint (último argumento) para variar la longitud de salida según sus requisitos. Entonces, para uno de 60 caracteres:
Una ligera variación: binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]dónde N=30.
dan-man
@ dan-man Gracias por este método opcional. Sin embargo, encuentro que consume al menos 5 veces más tiempo. ¿Lo notas también?
Ethan
0
agregando una respuesta más a la mezcla que funciona más rápido que la solución @eemz y también es completamente alfanumérica. Tenga en cuenta que esto no le da una respuesta 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 in range(width))
defrandom_choices_algo(width):return''.join(random.choices(LETTERS_AND_DIGITS, k=width))
print(generate_random_string(10))
# prints "48uTwINW1D"
Sin duda, esta no es la versión más liviana, pero es aleatoria y es fácil ajustar el alfabeto / longitud que desee:
import random
defgenerate(random_chars=12, alphabet="0123456789abcdef"):
r = random.SystemRandom()
return''.join([r.choice(alphabet) for i in range(random_chars)])
Respuestas:
Conseguí uno más rápido para la salida hexadecimal. Usando los mismos t1 y t2 que arriba:
>>> 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
solo hace una llamada al módulo aleatorio, no tiene que construir o leer una lista, y luego hace el resto con formato de cadena.fuente
string.hexdigits
: stackoverflow.com/a/15462293/311288 "string.hexdigits
devuelve0123456789abcdefABCDEF
(tanto en minúsculas como en mayúsculas), [...]. En su lugar, solo userandom.choice('0123456789abcdef')
".getrandbits
lugar derandrange
para hacerlo aún más rápido.'%030x' % random.getrandbits(60)
es incluso más rápido que'%030x' % random.randrange(16**30)
, probablemente porque no tiene que hacer ninguna conversión hacia / desde grandes empresasCadena hexadecimal de 30 dígitos:
>>> import os,binascii >>> print binascii.b2a_hex(os.urandom(15)) "c84766ca4a3ce52c3602bbf02ad1f7"
La ventaja es que obtiene la aleatoriedad directamente del sistema operativo, que puede ser más seguro y / o más rápido que random (), y no es necesario que lo sembre.
fuente
En Py3.6 +, otra opción es usar el nuevo
secrets
módulo estándar :>>> import secrets >>> secrets.token_hex(15) '8d9bad5b43259c6ee27d9aadc7b832' >>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable 'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
fuente
import string import random lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)] str = "".join(lst) print str ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
fuente
random.SystemRandom().choice
Solución dramáticamente más rápida que las de aquí:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits") 0.8056681156158447
fuente
%timeit '%030x' % randrange(16**30)
da 1000000 bucles, el mejor de 3: 1,61 µs por bucle mientras que%timeit '%0x' % getrandbits(30 * 4)
da 1000000 bucles, el mejor de 3: 396 ns por bucleNota:
random.choice(string.hexdigits)
es incorrecto, porquestring.hexdigits
devuelve0123456789abcdefABCDEF
(tanto en minúsculas como en mayúsculas), por lo que obtendrá un resultado sesgado, con el dígito hexadecimal 'c' el doble de probabilidades de aparecer que el dígito '7'. En su lugar, solo userandom.choice('0123456789abcdef')
.fuente
Otro método :
from Crypto import Random import binascii my_hex_value = binascii.hexlify(Random.get_random_bytes(30))
El punto es: el valor del byte siempre es igual al valor en hexadecimal .
fuente
función de una línea:
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)
fuente
In [1]: import random In [2]: hex(random.getrandbits(16)) Out[2]: '0x3b19'
fuente
Por cierto, este es el resultado del uso
timeit
de los dos enfoques que se han sugerido: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
fuente
Hay uno más rápido en comparación con lo que ha mencionado jcdyer. Esto requiere ~ 50% de su método más 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
Si quieres en base64:
binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]
Puede cambiar el parámetro de tamaño pasado a randint (último argumento) para variar la longitud de salida según sus requisitos. Entonces, para uno de 60 caracteres:
binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
fuente
binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]
dóndeN=30
.agregando una respuesta más a la mezcla que funciona más rápido que la solución @eemz y también es completamente alfanumérica. Tenga en cuenta que esto no le da una respuesta 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"
un rendimiento de referencia rápido
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
fuente
Sin duda, esta no es la versión más liviana, pero es aleatoria y es fácil ajustar el alfabeto / longitud que desee:
import random def generate(random_chars=12, alphabet="0123456789abcdef"): r = random.SystemRandom() return ''.join([r.choice(alphabet) for i in range(random_chars)])
fuente