2009-04-24 23 views
77

Ho cercato di trovare un modo più pitioso di generare una stringa casuale in python che possa scalare. In genere, vedo qualcosa di simile aStringhe casuali in Python 2.6 (Va bene?)

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

Fa schifo se si desidera generare una stringa lunga.

Ho pensato a random.getrandombits per un po 'e ho capito come convertirlo in un array di bit, quindi hex lo codifica. Utilizzando python 2.6 mi sono imbattuto nell'oggetto bitarray, che non è documentato. In qualche modo l'ho fatto funzionare, e sembra davvero veloce.

Genera una stringa casuale di 50 mi sul mio notebook in circa 3 secondi.

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] 

modificare

heikogerlach ha sottolineato che si trattava di un numero dispari di caratteri che causano il problema. Nuovo codice aggiunto per assicurarsi che sia sempre inviato da un numero pari di cifre esadecimali.

Ancora curioso di sapere se c'è un modo migliore per farlo è altrettanto veloce.

+1

Come faccio a fare questo in modo che possa includere solo i numeri, lettere, e sottolineare? (Questo include un trattino) – wenbert

+2

@wenbert '' .join (random.choice (string.letters + string.digits + "_") per i in xrange (lunghezza)) – yanjost

risposta

132
import os 
random_string = os.urandom(string_length) 

e se avete bisogno url stringa sicura:

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

(lunghezza random_string nota è più grande rispetto string_length in quel caso)

+0

Ah! Cosi 'semplice. Non pensavo che fosse multipiattaforma, ma apparentemente lo è. – mikelikespie

+0

Solo un follow-up, è davvero strano, ma almeno su OS X, il metodo getrandbits è 2-3 volte più veloce. – mikelikespie

+9

Probabilmente è perché os.urandom sarà un PRNG crittograficamente sicuro (di solito un codice stream) mentre random è un PRNG "normale" che di solito è molto più veloce da calcolare. – Joey

2

Sembra che il metodo di fromhex() si aspetta un numero pari di cifre esadecimali . La tua stringa è lunga 75 caratteri. Ricorda che something[:-1]esclude l'ultimo elemento! Basta usare something[:].

+0

C'era una L finale con __hex __(). Ho riscritto il codice di esempio. Ad ogni modo, penso che tu avessi ragione, richiedendo un numero pari di cifre – mikelikespie

5

Tratto da rapporto 1023290 bug in Python.org:

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

Inoltre, vedere i problemi 923643 e 1023290

+0

+1 per avermi ricordato la codifica esadecimale. – Buttons840

2

Per quanto riguarda l'ultimo esempio, la seguente correzione per assicurarsi che la linea è anche la lunghezza , qualunque sia il valore junk_len:

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

volte un uuid è abbastanza breve, e se non vi piacciono i trattini è possibile alw ays.replace ('-', '') li

from uuid import uuid4 

random_string = str(uuid4()) 

Se si vuole che un determinato periodo senza trattini

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

o usare 'uuid4(). Hex' per ottenere il valore senza trattini – davoclavo