创建一个包含30个字符的随机字符串的最轻量级方法是什么?如下所示?
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
一个十六进制的30位数字,如下所示?
8c6f78ac23b4a7b8c0182d7a89e9b1
答案 0 :(得分:102)
我得到一个更快的十六进制输出。使用与上述相同的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
只对随机模块进行一次调用,不必构建或读取列表,然后使用字符串格式化进行其余操作。
答案 1 :(得分:66)
30位十六进制字符串:
>>> import os,binascii
>>> print binascii.b2a_hex(os.urandom(15))
"c84766ca4a3ce52c3602bbf02ad1f7"
优势在于,它直接来自操作系统的随机性,这可能比random()更安全和/或更快,而且您不必为其播种。
答案 2 :(得分:27)
import string
import random
lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)]
str = "".join(lst)
print str
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
答案 3 :(得分:25)
在Py3.6 +中,另一种选择是使用新的标准secrets
模块:
>>> import secrets
>>> secrets.token_hex(15)
'8d9bad5b43259c6ee27d9aadc7b832'
>>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable
'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
答案 4 :(得分:24)
比这里的解决方案显着更快的解决方案:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits")
0.8056681156158447
答案 5 :(得分:15)
注意:random.choice(string.hexdigits)
不正确,因为string.hexdigits
返回0123456789abcdefABCDEF
(小写和大写),所以你会得到一个有偏差的结果,十六进制数字'c'可能是两倍显示为数字'7'。相反,只需使用random.choice('0123456789abcdef')
。
答案 6 :(得分:6)
另一种方法:
from Crypto import Random
import binascii
my_hex_value = binascii.hexlify(Random.get_random_bytes(30))
要点是:字节值始终等于十六进制值。
答案 7 :(得分:5)
单行功能:
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)
答案 8 :(得分:2)
顺便说一下,这是对{2}方法使用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
答案 9 :(得分:2)
与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)的size参数,以根据您的要求改变输出长度。所以,对于一个60 char:
binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
答案 10 :(得分:0)
<table id="test">
<tr>
<th>Firstname</th>
<th>Lastname</th>
</tr>
<tr>
<td>Peter</td>
<td>Griffin</td>
</tr>
<tr>
<td>Lois</td>
<td>Griffin</td>
<td style="border-style:none">extra</td>
</tr>
</table>
答案 11 :(得分:0)
为混合添加一个答案,该答案比@eemz解决方案执行得更快,并且也是完全字母数字的。请注意,这不是不会给您十六进制的答案。
import random
import string
LETTERS_AND_DIGITS = string.ascii_letters + string.digits
def random_choice_algo(width):
return ''.join(random.choice(LETTERS_AND_DIGITS) for i in range(width))
def random_choices_algo(width):
return ''.join(random.choices(LETTERS_AND_DIGITS, k=width))
print(generate_random_string(10))
# prints "48uTwINW1D"
快速基准收益率
from timeit import timeit
from functools import partial
arg_width = 10
print("random_choice_algo", timeit(partial(random_choice_algo, arg_width)))
# random_choice_algo 8.180561417000717
print("random_choices_algo", timeit(partial(random_choices_algo, arg_width)))
# random_choices_algo 3.172438014007639
答案 12 :(得分:0)
这肯定不是最轻便的版本,但它是随机的,可以轻松调整所需的字母/长度:
import random
def generate(random_chars=12, alphabet="0123456789abcdef"):
r = random.SystemRandom()
return ''.join([r.choice(alphabet) for i in range(random_chars)])