2009-04-24 29 views
77

He estado tratando de encontrar una forma más pitónica de generar cadenas aleatorias en python que también puedan escalar. Por lo general, veo algo similar aCadenas aleatorias en Python 2.6 (¿Está bien?)

''.join(random.choice(string.letters) for i in xrange(len)) 

Es un asco si desea generar cadena larga.

He estado pensando en random.getrandombits por un tiempo, y descubriendo cómo convertir eso en una matriz de bits, y luego codificarlo en hexadecimal. Usando Python 2.6 me encontré con el objeto bitarray, que no está documentado. De alguna manera lo hice funcionar, y parece realmente rápido.

Genera una secuencia aleatoria de 50 mil en mi computadora portátil en solo 3 segundos.

def rand1(leng): 
    nbits = leng * 6 + 1 
    bits = random.getrandbits(nbits) 
    uc = u"%0x" % bits 
    newlen = int(len(uc)/2) * 2 # we have to make the string an even length 
    ba = bytearray.fromhex(uc[:newlen]) 
    return base64.urlsafe_b64encode(str(ba))[:leng] 

edición

heikogerlach señaló que se trataba de un número impar de caracteres que causan el problema. Se agregó un nuevo código para asegurarse de que siempre envía desde hex un número par de dígitos hexadecimales.

Siendo curioso, si hay una forma mejor de hacerlo, es igual de rápido.

+1

¿Cómo hago esto para que sólo incluirá los números, letras, y ¿guion bajo? (Esto incluye un guion) – wenbert

+2

@wenbert '' .join (random.choice (string.letters + string.digits + "_") para i en xrange (longitud)) – yanjost

Respuesta

132
import os 
random_string = os.urandom(string_length) 

y si necesita String url segura:

import os 
random_string = os.urandom(string_length).hex() 

(nota longitud random_string es lo más grande que string_length en ese caso)

+0

¡Ah! Tan sencillo. No pensé que era multiplataforma, pero aparentemente lo es. – mikelikespie

+0

Solo un seguimiento, es realmente extraño, pero al menos en OS X, el método getrandbits es 2-3 veces más rápido. – mikelikespie

+9

Eso es probablemente porque os.urandom será un PRNG criptográficamente seguro (generalmente un cifrado de flujo) mientras que al azar es un PRNG "normal" que generalmente es mucho más rápido de calcular. – Joey

2

Parece el método fromhex() espera un número par de dígitos hexadecimales . Tu cadena tiene 75 caracteres. Tenga en cuenta que something[:-1]excluye el último elemento! Simplemente use something[:].

+0

Había una L posterior con __hex __(). Reescribí el código de muestra. De todos modos, creo que estaba en lo cierto con que requiere un número par de dígitos – mikelikespie

5

Tomado del informe de errores en 1023290 Python.org:

junk_len = 1024 
junk = (("%%0%dX" % junk_len) % random.getrandbits(junk_len * 
8)).decode("hex") 

Además, vea los temas 923643 y 1023290

+0

+1 para recordarme la codificación hexadecimal. – Buttons840

2

Con respecto a este último ejemplo, la revisión siguiente para asegurarse de que la línea es igual longitud , cualquiera que sea el valor junk_len:

junk_len = 1024 
junk = (("%%0%dX" % (junk_len * 2)) % random.getrandbits(junk_len * 8)).decode("hex") 
9

veces un UUID es lo suficientemente corto y si no te gusta los guiones Puede alw ays.replace ('-', '') que

from uuid import uuid4 

random_string = str(uuid4()) 

Si quieres que una longitud específica sin guiones

random_string_length = 16 
str(uuid4()).replace('-', '')[:random_string_length] 
+0

o use 'uuid4(). Hex' para obtener el valor sin guiones – davoclavo