最轻量级的方法来创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)