最快的确定性方法
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)
安全的URL方法
使用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中使用,因为与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)
更进一步的讨论
Python 3.9中secrets.token_urlsafe的实现
tok = token_bytes(nbytes)
base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii')
由于ASCII字节的.decode()
比.decode('ascii')
更快,当nbytes % 6 == 0
时,.rstrip(b'=')
无用。
base64.urlsafe_b64encode(secrets.token_bytes(nbytes)).decode()
更快(约20%)。
在Windows10上,当nbytes为6(8个字符)时,基于字节的方法比文本方法快2倍,当nbytes为24(32个字符)时,快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)
可能更好。