最快的确定性方法
import random
import binascii
e = random.Random(seed)
binascii.b2a_base64(random.getrandbits(48).to_bytes(6, 'little'), newline=False)
最快的系统随机方法
import os
import binascii
binascii.b2a_base64(os.urandom(6), newline=False)
网址安全方法
利用os.urandom
import os
import base64
base64.urlsafe_b64encode(os.urandom(6)).decode()
使用random.Random.choices
(缓慢,但灵活)
import random
import string
alphabet = string.ascii_letters + string.digits + '-_'
''.join(random.choices(alphabet, k=8))
使用random.Random.getrandbits
(快于random.Random.randbytes
)
import random
import base64
base64.urlsafe_b64encode(random.getrandbits(48).to_bytes(6, 'little')).decode()
使用random.Random.randbytes
(python >= 3.9)
import random
import base64
base64.urlsafe_b64encode(random.randbytes(6)).decode()
使用random.SystemRandom.randbytes
(python >= 3.9)
import random
import base64
e = random.SystemRandom()
base64.urlsafe_b64encode(e.randbytes(6)).decode()
random.SystemRandom.getrandbits
如果 python >= 3.9,则不建议使用,因为它需要 2.5 倍的时间,random.SystemRandom.randbytes
并且更复杂。
使用secrets.token_bytes
(python >= 3.6)
import secrets
import base64
base64.urlsafe_b64encode(secrets.token_bytes(6)).decode()
使用secrets.token_urlsafe
(python >= 3.6)
import secrets
secrets.token_urlsafe(6) # 6 byte base64 has 8 char
进一步讨论
python3.9中的secrets.token_urlsafe实现
tok = token_bytes(nbytes)
base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii')
由于 ASCII 字节.decode()
比 快.decode('ascii')
,并且.rstrip(b'=')
在nbytes % 6 == 0
.
base64.urlsafe_b64encode(secrets.token_bytes(nbytes)).decode()
更快(~20%)。
在 Windows10 上,基于字节的方法在 nbytes=6(8 char) 时快 2 倍,在 nbytes=24(32 char) 时快 5 倍。
在 Windows 10(我的笔记本电脑)上,secrets.token_bytes
花费类似的时间random.Random.randbytes
,并且base64.urlsafe_b64encode
比随机字节生成花费更多的时间。
在 Ubuntu 20.04(我的云服务器,可能缺少熵)上,secrets.token_bytes
花费的时间比 多 15 倍random.Random.randbytes
,但花费的时间类似random.SystemRandom.randbytes
由于secrets.token_bytes
使用random.SystemRandom.randbytes
use os.urandom
(因此它们完全相同),如果性能至关重要,您可以替换secrets.token_bytes
为。os.urandom
在 Python3.9 中,base64.urlsafe_b64encode
是 和 的组合base64.b64encode
,bytes.translate
因此要多花约 30% 的时间。
random.Random.randbytes(n)
由 实现random.Random.getrandbits(n * 8).to_bytes(n, 'little')
,因此慢 3 倍。(但是,random.SystemRandom.getrandbits
用 实现random.SystemRandom.randbytes
)
base64.b32encode
速度要慢得多(6 字节为 5 倍,480 字节为 17 倍),base64.b64encode
因为其中有很多 python 代码base64.b32encode
,但base64.b64encode
只需调用binascii.b2a_base64
(C 实现)。
不过里面有个python分支语句,if altchars is not None:
在base64.b64encode
处理小数据时会引入不可忽略的开销,binascii.b2a_base64(data, newline=False)
可能会更好。