Python 2.6中的随机字符串(可以吗?)


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指出,导致此问题的字符数量奇多。添加了新代码以确保始终从十六进制发送偶数个十六进制数字。

仍然好奇是否有更快的方法可以做到这一点。


1
我如何做到这一点,使其仅包含数字,字母和下划线?(包括破折号)
wenbert 2010年

2
@wenbert''.join(random.choice(string.letters + string.digits +“ _”)for i in xrange(length))
yanjost 2011年

Answers:


130
import os
random_string = os.urandom(string_length)

以及是否需要url安全字符串:

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

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


9
这可能是因为os.urandom将是加密安全的PRNG(通常是流密码),而random是“正常” PRNG,通常可以更快地进行计算。
乔伊,

6
有没有办法使用它来生成ASCII字符串而不是unicode?例如,因此可以在URL中使用字符串。
Derek Dahmer'2

8
您可以像第一个示例一样使用random.choice,string.digits和string.letters:>>> import random,string >>>''.join(random.choice(string.letters + string.digits)for i in xrange(10))'FywhcRLmh1'(我假设您没有像op那样生成巨大的字符串,因为它用于URL ...)
JJ Geewax 2010年

63
具体来说,我使用了以下代码:base64.urlsafe_b64encode(os.urandom(30))
jricher 2011年

4
很抱歉在旧主题中重新发布。有什么方法只能使用os.urandom(string_length)和获取ASCII字母吗?...由于python是一种解释型语言,因此一次生成一个字节的循环看起来非常昂贵。
2011年

10

有时候一个uuid足够短,如果您不喜欢破折号,您可以随时替换('-','')

from uuid import uuid4

random_string = str(uuid4())

如果您希望它的长度没有破折号

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

或用于uuid4().hex获取没有连字符的值
davoclavo 2015年

6

取自Python.org的1023290错误报告:

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

另外,请参阅问题9236431023290


2

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


__hex __()后面有一个L。我重写了示例代码。无论如何,我认为您的要求是偶数个数字是正确的
mikelikespie

2

关于最后一个示例,以下修复程序确保无论junk_len值如何,行均等长:

junk_len = 1024
junk =  (("%%0%dX" % (junk_len * 2)) % random.getrandbits(junk_len * 8)).decode("hex")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.