Случайные строки в Python 2.6 (это нормально?)

Я пытался найти более питонический способ создания случайной строки в python, который также может масштабироваться. Обычно я вижу что-то похожее на

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

Отстойно, если вы хотите сгенерировать длинную строку.

Некоторое время я думал о random.getrandombits и выяснял, как преобразовать это в массив бит, а затем закодировать его в шестнадцатеричном формате. Используя python 2.6, я наткнулся на объект битового массива, который не задокументирован. Каким-то образом я заставил его работать, и это кажется очень быстрым.

Он генерирует на моем ноутбуке случайную строку размером 50 мил всего за 3 секунды.

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]

изменить

Хейкогерлах указал, что причиной проблемы было нечетное количество символов. Добавлен новый код, чтобы он всегда отправлял из шестнадцатеричного числа четное число шестнадцатеричных цифр.

По-прежнему любопытно, есть ли лучший способ сделать это так же быстро.


person mikelikespie    schedule 24.04.2009    source источник
comment
Как сделать так, чтобы в него входили только цифры, буквы и подчеркивание? (Это включает тире)   -  person wenbert    schedule 30.12.2010
comment
@wenbert '' .join (random.choice (string.letters + string.digits + _) для i в xrange (длина))   -  person yanjost    schedule 31.08.2011


Ответы (5)


import os
random_string = os.urandom(string_length)

и если вам нужна безопасная строка URL:

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

(обратите внимание, что в этом случае длина random_string больше, чем string_length)

person Seun Osewa    schedule 24.04.2009
comment
Ах! Так просто. Я не думал, что это кроссплатформенный, но, видимо, это так. - person mikelikespie; 24.04.2009
comment
Просто продолжение, это действительно странно, но, по крайней мере, в OS X метод getrandbits работает в 2-3 раза быстрее. - person mikelikespie; 24.04.2009
comment
Вероятно, это потому, что os.urandom будет криптографически безопасным ГПСЧ (обычно это потоковый шифр), в то время как random - это обычный ГПСЧ, который обычно вычисляется намного быстрее. - person Joey; 24.04.2009
comment
Есть ли способ использовать это для генерации строк ASCII, а не Unicode? Например, строка может использоваться в URL-адресе. - person Derek Dahmer; 06.02.2010
comment
Вы можете использовать random.choice, string.digits и string.letters, как в первом примере: ››› import random, string ››› '' .join (random.choice (string.letters + string.digits) для i in xrange (10)) 'FywhcRLmh1' (я предполагаю, что вы не генерируете огромную строку, такую ​​как op, поскольку она для URL ...) - person JJ Geewax; 19.03.2010
comment
Для URL-адресов можно использовать string.ascii_letters. - person jholster; 22.05.2010
comment
@Derek: вы можете закодировать случайную строку в base64 для URL-адреса. - person Seun Osewa; 23.10.2010
comment
В частности, я использовал это: base64.urlsafe_b64encode (os.urandom (30)) - person jricher; 29.03.2011
comment
Извините за повторную публикацию в старой ветке. Есть ли способ использовать os.urandom(string_length) и получать только буквы ASCII? ... Поскольку python является интерпретируемым языком, цикл, генерирующий по одному байту, кажется довольно дорогостоящим. - person BiGYaN; 19.10.2011
comment
@BiGYaN: jricher дал решение для того, что возвращает строку в кодировке base64, то есть: только буквы ASCII. - person ereOn; 04.09.2012

Иногда uuid бывает достаточно коротким, и если вам не нравятся тире, вы всегда можете заменить их ('-', '')

from uuid import uuid4

random_string = str(uuid4())

Если вам нужна определенная длина без тире

random_string_length = 16
str(uuid4()).replace('-', '')[:random_string_length]
person Joelbitar    schedule 31.08.2012
comment
или используйте uuid4().hex, чтобы получить значение без дефисов - person davoclavo; 31.03.2015

Взято из отчета об ошибке 1023290 на Python.org:

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

Также см. Проблемы 923643 и 1023290

person fdr    schedule 24.04.2009

Кажется, что метод fromhex() ожидает четное количество шестнадцатеричных цифр. Ваша строка состоит из 75 символов. Имейте в виду, что something[:-1] исключает последний элемент! Просто используйте something[:].

person Community    schedule 24.04.2009
comment
В конце L был __hex __ (). Я переписал пример кода. В любом случае, я думаю, вы были правы, требуя четное количество цифр - person mikelikespie; 24.04.2009

Что касается последнего примера, следующее исправление, чтобы убедиться, что длина строки одинакова, независимо от значения junk_len:

junk_len = 1024
junk =  (("%%0%dX" % (junk_len * 2)) % random.getrandbits(junk_len * 8)).decode("hex")
person user115995    schedule 02.06.2009