77

我一直在尝试找到一种更 Pythonic 的方式来在 python 中生成随机字符串,它也可以扩展。通常,我看到类似于

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

如果你想生成长字符串,那就太糟糕了。

我一直在考虑 random.getrandombits ,并弄清楚如何将其转换为位数组,然后对其进行十六进制编码。使用 python 2.6 我遇到了未记录的 bitarray 对象。不知何故,我让它工作了,它似乎真的很快。

它会在大约 3 秒内在我的笔记本上生成一个 5000 万个随机字符串。

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]

编辑

heikogerlach 指出是奇数个字符导致了这个问题。添加了新代码以确保它始终从十六进制发送偶数个十六进制数字。

仍然很好奇是否有更好的方法来做到这一点同样快。

4

5 回答 5

130
import os
random_string = os.urandom(string_length)

如果您需要 url 安全字符串:

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

(注意在这种情况下 random_string 长度大于 string_length )

于 2009-04-24T09:09:39.070 回答
10

有时 uuid 足够短,如果你不喜欢破折号,你可以随时.replace('-', '') 他们

from uuid import uuid4

random_string = str(uuid4())

如果你想要一个没有破折号的特定长度

random_string_length = 16
str(uuid4()).replace('-', '')[:random_string_length]
于 2012-08-31T15:32:38.360 回答
6

摘自 Python.org 上的1023290错误报告:

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

另请参阅问题9236431023290

于 2009-04-24T17:04:55.170 回答
2

似乎该fromhex()方法需要偶数个十六进制数字。您的字符串长度为 75 个字符。请注意,something[:-1] 不包括最后一个元素!只需使用something[:].

于 2009-04-24T09:09:45.420 回答
2

关于最后一个示例,无论 junk_len 值如何,以下修复以确保该行是偶数长度:

junk_len = 1024
junk =  (("%%0%dX" % (junk_len * 2)) % random.getrandbits(junk_len * 8)).decode("hex")
于 2009-06-02T13:24:54.330 回答