最快的确定性方法
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()
如果python >= 3.9,不推荐random.SystemRandom.getrandbits,因为与random.SystemRandom.randbytes相比,它需要2.5倍的时间并且更复杂。
使用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 花费的时间比 random.Random.randbytes 多 15 倍,但与 random.SystemRandom.randbytes 花费的时间相似
由于secrets.token_bytes 使用random.SystemRandom.randbytes 使用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 比base64.b64encode 慢得多(6 字节为 5 倍,480 字节为 17 倍),因为base64.b32encode 中有很多 python 代码,但base64.b64encode 只需调用binascii.b2a_base64(C 实现) .
但是base64.b64encode中有一个python分支语句if altchars is not None:,在处理小数据时会引入不可忽略的开销,binascii.b2a_base64(data, newline=False)可能会更好。