最快的确定性方法
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.randbytesuse 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)可能会更好。