By default the Python random module use the Mersenne Twister [PRNG](<https://en.wikipedia.org/wiki/Pseudorandom_number_generator>) to generate random numbers, which, although suitable in domains like simulations, fails to meet security requirements in more demanding environments.

In order to create a cryptographically secure pseudorandom number, one can use [SystemRandom](<https://docs.python.org/3/library/random.html#random.SystemRandom>) which, by using os.urandom, is able to act as a Cryptographically secure pseudorandom number generator, CPRNG.

The easiest way to use it simply involves initializing the SystemRandom class. The methods provided are similar to the ones exported by the random module.

from random import SystemRandom
secure_rand_gen = SystemRandom()

In order to create a random sequence of 10 ints in range [0, 20], one can simply call randrange():

print([secure_rand_gen.randrange(10) for i in range(10)])
# [9, 6, 9, 2, 2, 3, 8, 0, 9, 9]

To create a random integer in a given range, one can use randint:

print(secure_rand_gen.randint(0, 20))
# 5

and, accordingly for all other methods. The interface is exactly the same, the only change is the underlying number generator.

You can also use [os.urandom](<https://docs.python.org/3/library/os.html#os.urandom>) directly to obtain cryptographically secure random bytes.