Fastest Deterministic Method
import random
import binascii
e = random.Random(seed)
binascii.b2a_base64(e.getrandbits(48).to_bytes(6, 'little'), newline=False)
Fastest System Random Method
import os
import binascii
binascii.b2a_base64(os.urandom(6), newline=False)
Url Safe Methods
Use os.urandom
import os
import base64
base64.urlsafe_b64encode(os.urandom(6)).decode()
Use random.Random.choices
(slow, but flexible)
import random
import string
alphabet = string.ascii_letters + string.digits + '-_'
''.join(random.choices(alphabet, k=8))
Use random.Random.getrandbits
(faster than random.Random.randbytes
)
import random
import base64
base64.urlsafe_b64encode(random.getrandbits(48).to_bytes(6, 'little')).decode()
Use random.Random.randbytes
(python >= 3.9)
import random
import base64
base64.urlsafe_b64encode(random.randbytes(6)).decode()
Use random.SystemRandom.randbytes
(python >= 3.9)
import random
import base64
e = random.SystemRandom()
base64.urlsafe_b64encode(e.randbytes(6)).decode()
random.SystemRandom.getrandbits
is not recommended if python >= 3.9, since it takes 2.5x time comparing to random.SystemRandom.randbytes
and is more complicated.
Use secrets.token_bytes
(python >= 3.6)
import secrets
import base64
base64.urlsafe_b64encode(secrets.token_bytes(6)).decode()
Use secrets.token_urlsafe
(python >= 3.6)
import secrets
secrets.token_urlsafe(6) # 6 byte base64 has 8 char
Further Discussion
secrets.token_urlsafe implementation in python3.9
tok = token_bytes(nbytes)
base64.urlsafe_b64encode(tok).rstrip(b'=').decode('ascii')
Since ASCII bytes .decode()
is faster than .decode('ascii')
,
and .rstrip(b'=')
is useless when nbytes % 6 == 0
.
base64.urlsafe_b64encode(secrets.token_bytes(nbytes)).decode()
is faster (~20%).
On Windows10, bytes based method is 2x faster when nbytes=6(8 char), and 5x faster when nbytes=24(32 char).
On Windows 10(my laptop), secrets.token_bytes
take similar time like random.Random.randbytes
, and base64.urlsafe_b64encode
take more time than random bytes generation.
On Ubuntu 20.04(my cloud server, may lack entropy), secrets.token_bytes
take 15x more time than random.Random.randbytes
, but take similar time like random.SystemRandom.randbytes
Since secrets.token_bytes
use random.SystemRandom.randbytes
use os.urandom
(thus they are exactly same), you may replace secrets.token_bytes
by os.urandom
if performance is crucial.
In Python3.9, base64.urlsafe_b64encode
is a combination of base64.b64encode
and bytes.translate
, thus take ~30% more time.
random.Random.randbytes(n)
is implemented by random.Random.getrandbits(n * 8).to_bytes(n, 'little')
, thus 3x slower. (However, random.SystemRandom.getrandbits
is implemented with random.SystemRandom.randbytes
)
base64.b32encode
is dramatically slower(5x for 6 bytes, 17x for 480 bytes) than base64.b64encode
because there are a lots of python code in base64.b32encode
, but base64.b64encode
just call binascii.b2a_base64
(C implemented).
However, there is a python branch statement if altchars is not None:
in base64.b64encode
, which will introduce not negligible overhead when process small data, binascii.b2a_base64(data, newline=False)
may be better.
filename = String.Format("zhry{0:0000}", counter++);
– Bucephalus