2009-04-24 11 views
77

Próbowałem znaleźć bardziej pytonowy sposób generowania losowego ciągu znaków w pythonie, który również może skalować. Zazwyczaj widzę coś podobnego do tego, co jest w stanie wygenerować długi łańcuch.Losowe ciągi w Pythonie 2.6 (czy to jest w porządku?)

Myślałem przez chwilę o random.getrandombits i zastanawiałem się, jak przekonwertować to na tablicę bitów, a następnie zakodować je w szesnastkowy. Używając Pythona 2.6 natknąłem się na obiekt bitarray, który nie jest udokumentowany. Jakoś mi się to udało i wygląda na to, że jest naprawdę szybki.

Generuje losowy ciąg 50 mil na moim notesie w ciągu zaledwie 3 sekund.

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] 

edit

heikogerlach podkreślić, że była nieparzysta liczba znaków powodujących problem. Dodano nowy kod, aby zawsze był wysyłany z heksadecymalnej liczby cyfr szesnastkowych.

Wciąż ciekawy, czy jest lepszy sposób robienia tego równie szybko.

+1

Jak zrobić to tak, że będzie ona zawierać tylko cyfry, litery i podkreślać? (Zawiera myślnik) – wenbert

+2

@wenbert '' .join (random.choice (string.letters + string.digits + "_") dla i w xrange (długość)) – yanjost

Odpowiedz

132
import os 
random_string = os.urandom(string_length) 

i jeśli trzeba url bezpieczny ciąg:

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

(uwaga długość random_string jest największa niż string_length w tym przypadku)

+0

Ah! Tak prosty. Nie sądziłem, że jest to platforma wieloplatformowa, ale wygląda na to, że jest. – mikelikespie

+0

Po pewnym czasie, to naprawdę dziwne, ale przynajmniej na OS X, metoda getrandbits jest 2-3x szybsza. – mikelikespie

+9

To pewnie dlatego, że os.urandom będzie kryptograficznie bezpieczny PRNG (zwykle szyfrem strumieniowym), podczas gdy losowy jest "normalnym" PRNG, który zwykle jest szybszy do obliczenia. – Joey

2

Wydaje się, że metoda fromhex() oczekuje parzystą liczbę cyfr szesnastkowych . Twój ciąg ma 75 znaków. Należy pamiętać, że something[:-1]wyklucza ostatni element z! Po prostu użyj something[:].

+0

Występował ciąg L z __hex __(). Przepisałem przykładowy kod. Tak czy inaczej, sądzę, że masz rację, wymagając parzystej liczby cyfr – mikelikespie

5

pochodzą ze sprawozdania 1023290 bug na Python.org:

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

Zobacz także kwestie 923643 i 1023290

+0

+1 za przypomnienie mi kodu szesnastkowego. – Buttons840

2

Odnośnie ostatniej przykład następujący dylemat aby upewnić się, że linia jest nawet długość , niezależnie od wartości junk_len:

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

Czasami uuid jest wystarczająco krótki i jeśli nie podoba ci się kreska, możesz ays.replace („-”, „”) im

from uuid import uuid4 

random_string = str(uuid4()) 

jeśli chcesz konkretną długość bez kresek

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

lub użyj 'uuid4(). Hex', aby uzyskać wartość bez myślników – davoclavo

Powiązane problemy