创建随机字符串和随机十六进制数的最轻量方式
怎样才能最简单地生成一个30个字符的随机字符串,比如下面这个?
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
还有一个30位的十六进制数字,像下面这个?
8c6f78ac23b4a7b8c0182d7a89e9b1
15 个回答
94
30位十六进制字符串:
>>> import os
>>> os.urandom(15).hex()
"c84766ca4a3ce52c3602bbf02ad1f7"
这样做的好处是,它直接从操作系统获取随机数,这可能比random()方法更安全或者更快,而且你不需要手动设置种子。
95
在Python 3.6及以上版本中,还有一个新选择,就是使用标准的secrets
模块:
生成随机的字母数字字符串:
In []:
import secrets
n = 30*3//4 # see note
secrets.token_urlsafe(n)
Out[]:
'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
注意:token_urlsafe()
使用的是base64编码,这意味着你需要把请求的数量减少3//4
,才能得到确切的30
。另外,你也可以把返回的字符串截取到前30个字符。
返回的字符串可能还会包含_-
,不太清楚这样是否可以。
生成随机的十六进制字符串:
In []:
secrets.token_hex(15)
Out[]:
'8d9bad5b43259c6ee27d9aadc7b832'
时间记录:
In []:
%timeit secrets.token_urlsafe(n)
Out[]:
788 ns ± 4.32 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
In []:
%timeit secrets.token_hex(15)
Out[]:
631 ns ± 2.86 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
143
我这里有一个更快的方法来输出十六进制的结果。使用上面提到的同样的 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
只需要调用一次随机模块,不用去创建或读取一个列表,然后就用字符串格式化来完成剩下的工作。