最轻量级的方法来创build一个随机的string和一个随机的hex数字

什么是最轻量级的方式来创build一个30个字符的随机string,如下所示?

ufhy3skj5nca0d2dfh9hwd2tbk9sw1

还有一个像下面这样的30位数的hex数?

8c6f78ac23b4a7b8c0182d7a89e9b1

我得到了hex输出更快的一个。 使用与上面相同的t1和t2:

>>> t1 = timeit.Timer("''.join(random.choice('0123456789abcdef') for n in xrange(30))", "import random") >>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii") >>> t3 = timeit.Timer("'%030x' % random.randrange(16**30)", "import random") >>> for t in t1, t2, t3: ... t.timeit() ... 28.165037870407104 9.0292739868164062 5.2836320400238037 

t3只对一个随机模块进行一次调用,不必build立或读取一个列表,然后用string格式化。

30位hexstring:

 >>> import os,binascii >>> print binascii.b2a_hex(os.urandom(15)) "c84766ca4a3ce52c3602bbf02ad1f7" 

好处是,它直接从操作系统获得随机性,这可能比random()更安全和/或更快,并且您不必将其种子。

 import string import random lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)] str = "".join(lst) print str ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb 

比这里显着更快的解决scheme:

 timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits") 0.8056681156158447 

注意: random.choice(string.hexdigits)是不正确的,因为string.hexdigits返回0123456789abcdefABCDEF (小写和大写),所以你会得到一个有偏见的结果,hex数字'c' 7' 。 相反,只需使用random.choice('0123456789abcdef')

在Py3.6中,另一种select是使用新的标准secrets模块:

 >>> import secrets >>> secrets.token_hex(15) '8d9bad5b43259c6ee27d9aadc7b832' >>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable 'teRq7IqhaRU0S3euX1ji9f58WzUkrg' 

另一种方法:

 from Crypto import Random import binascii my_hex_value = binascii.hexlify(Random.get_random_bytes(30)) 

重点是: 字节值总是等于hex的值

顺便说一句,这是使用timeit的两种方法的结果:

使用random.choice()

 >>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string") >>> t1.timeit() 69.558588027954102 

使用binascii.b2a_hex()

 >>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii") >>> t2.timeit() 16.288421154022217 

与jcdyer提到的相比,速度更快。 这需要约50%的最快的方法。

 from numpy.random.mtrand import RandomState import binascii rand = RandomState() lo = 1000000000000000 hi = 999999999999999999 binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:30] >>> timeit.Timer("binascii.b2a_hex(rand.randint(lo,hi,2).tostring())[:30]", \ ... 'from __main__ import lo,hi,rand,binascii').timeit() 1.648831844329834 <-- this is on python 2.6.6 2.253110885620117 <-- this on python 2.7.5 

如果你想在base64中:

 binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30] 

您可以更改传递给randint(last arg)的大小参数,以根据您的要求改变输出长度。 所以,对于一个60个字符:

 binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60] 

单线function:

 import random import string def generate_random_key(length): return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(length)) print generate_random_key(30)