random

One hidden Mersenne Twister generator behind a set of module functions: random() for floats, randint() for ints, choice/sample/shuffle for sequences. Seed it and every run repeats exactly. Never use it for passwords or tokens: that is what the secrets module is for.

NumbersAll Python 3 versionsLive demo
Import
import random
from random import randint, choice, shuffle
Generator
Mersenne Twister (MT19937): 53-bit floats, period 2**19937-1
Security
Not cryptographically secure: use secrets (token_hex, token_urlsafe, choice) for passwords, tokens and keys
Seeding
From os.urandom() at import; random.seed(x) makes the sequence repeatable
Module functions
Bound methods of one hidden random.Random instance; create your own Random() for an independent stream
CLI
python -m random 6 (3.13+): an int from 1 to 6, a float, or a choice

Demo

Live evaluation
Seed the generator and roll ten dice. The same seed always gives the same rolls; a different seed (an int or a string) gives a different sequence.
Try:
Inputs
seedint | stran int or a string
Code
import random
random.seed(42)
[random.randint(1, 6) for _ in range(10)]
Result
[6, 1, 1, 6, 3, 2, 2, 2, 6, 1]

seed(42) and seed(-42) give identical rolls: an int seed is used by its absolute value. A string seed is hashed with SHA-512 into a large int, so "hello" starts a completely different sequence. In the pick tab, sample() refuses to draw 2 distinct items from a 1-item list (ValueError), while choices() happily repeats; an empty list fails already at choice() with IndexError.

Members

Functions14
LIVE
random.binomialvariate
binomialvariate(n=1, p=0.5)
The number of successes in n independent trials with success probability p — an int from 0 to n. New in Python 3.12.
LIVE
random.choice
choice(seq)
One random element of a non-empty sequence (list, tuple, str, range); IndexError when the sequence is empty.
LIVE
random.choices
choices(population, weights=None, *, cum_weights=None, k=1)
k random picks from a population WITH replacement, optionally weighted by relative or cumulative weights. Always returns a list.
LIVE
random distributions: expovariate, triangular, …
expovariate(lambd=1.0) / triangular(low=0.0, high=1.0, mode=None) / lognormvariate(mu, sigma) / paretovariate(alpha) / weibullvariate(alpha, beta) / vonmisesvariate(mu, kappa)
Six continuous distributions: exponential waiting times, triangular estimates, log-normal sizes, Pareto tails, Weibull lifetimes and von Mises angles.
LIVE
random.gammavariate / betavariate
gammavariate(alpha, beta) / random.betavariate(alpha, beta)
Gamma-distributed positive floats (shape alpha, scale beta) and beta-distributed floats between 0 and 1 — the second is built from two gamma draws.
LIVE
random.gauss / normalvariate
gauss(mu=0.0, sigma=1.0) / random.normalvariate(mu=0.0, sigma=1.0)
Normally distributed floats (the bell curve) with mean mu and standard deviation sigma. gauss is a bit faster and caches a second value; normalvariate is the thread-safe one.
LIVE
random.getrandbits / randbytes
getrandbits(k) / random.randbytes(n)
Raw randomness: getrandbits(k) returns a non-negative int with k random bits, randbytes(n) returns n random bytes (3.9+). Not for keys or tokens.
LIVE
random.getstate / setstate
getstate() / random.setstate(state)
Snapshot the generator and restore it later: getstate() returns (3, 625-int tuple, gauss cache), setstate() rewinds to exactly that point.
LIVE
random.randint / randrange
randint(a, b) / random.randrange(start, stop=None, step=1)
Random integers: randint(a, b) includes both ends, randrange(start, stop, step) picks from range(start, stop, step) and excludes stop.
LIVE
random.random
random()
The next random float in the half-open range 0.0 <= x < 1.0: a multiple of 2**-53, built from two 32-bit Mersenne Twister outputs.
LIVE
random.sample
sample(population, k, *, counts=None)
k distinct picks from a sequence, without replacement: lottery numbers, raffle winners, a random subset. Returns a new list in selection order.
LIVE
random.seed
seed(a=None, version=2)
Initialize the generator so the same seed replays the same sequence of random numbers: ints by absolute value, str/bytes via SHA-512, None from the operating system.
LIVE
random.shuffle
shuffle(x)
Shuffle a list in place (Fisher-Yates) and return None. For a shuffled copy, or an immutable sequence, use sample(x, k=len(x)).
LIVE
random.uniform
uniform(a, b)
A random float between a and b, computed as a + (b - a) * random(); a and b may come in either order.

Common patterns

Reproducible runs
Seed once at program start (or per test) so a bug or an experiment can be replayed exactly.
import random
random.seed(2026)
sample = random.sample(population, 100)
An independent generator
A Random instance has its own state: library code calling random.random() cannot disturb it.
import random
rng = random.Random(42)
roll = rng.randint(1, 6)
Secure tokens: secrets, not random
Passwords, reset links, API keys and session ids need an unpredictable source.
import secrets
token = secrets.token_urlsafe(32)
pin = ''.join(secrets.choice('0123456789') for _ in range(6))
Weighted pick
choices() takes relative weights; k is the number of picks (with replacement).
import random
loot = random.choices(['common', 'rare', 'epic'], weights=[80, 15, 5], k=10)

Examples

1. A float in [0.0, 1.0)
import random random.seed(42) random.random()
Returns
0.6394267984578837
2. Dice: both ends included
import random random.seed(42) [random.randint(1, 6) for _ in range(10)]
Returns
[6, 1, 1, 6, 3, 2, 2, 2, 6, 1]
3. Pick one item
import random random.seed(42) random.choice(['rock', 'paper', 'scissors'])
Returns
'scissors'
4. Lottery: six distinct numbers
import random random.seed(42) random.sample(range(1, 50), 6)
Returns
[41, 8, 2, 18, 16, 15]
5. Shuffle a list in place
import random random.seed(42) cards = ['A', 'K', 'Q', 'J'] random.shuffle(cards) cards
Returns
['Q', 'K', 'J', 'A']
6. Same seed, same numbers
import random random.seed(42) a = random.random() random.seed(42) b = random.random() a == b
Returns
True
7. Secure tokens come from secrets
import secrets len(secrets.token_hex(16))
Returns
32

Pitfalls

1. Assigning the result of shuffle()
shuffle() reorders the list in place and returns None, so x = random.shuffle(x) throws the list away.
x = shuffle(x)
import random
random.seed(42)
cards = ['A', 'K', 'Q', 'J']
cards = random.shuffle(cards)
print(cards)
None
shuffle, then use x
import random
random.seed(42)
cards = ['A', 'K', 'Q', 'J']
random.shuffle(cards)
cards
['Q', 'K', 'J', 'A']
2. Generating passwords or tokens with random
Mersenne Twister output is predictable: the same seed reproduces the "secret", and 624 consecutive 32-bit outputs are enough to reconstruct the whole state. Use secrets, which draws from the operating system.
random token
import random
random.seed(2026)
''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=12))
'ess4divu2t01'
secrets token
import secrets
token = secrets.token_urlsafe(16)
len(token)
22

When to use

Use it
  • Simulations, games, randomized tests and sampling data
  • Reproducible experiments: seed() or Random(seed) replays the exact sequence
  • Shuffling, picking winners, weighted random choices
Reach for something else
  • Passwords, tokens, keys, salts, anything an attacker must not guess → secrets
  • Large numeric arrays of random numbers → numpy.random (vectorized)
  • Sharing one sequence between threads that must be reproducible → one Random instance per thread

Notes

CPython impl
Modules/_randommodule.c implements the Mersenne Twister core (seed, random, getrandbits, getstate, setstate); everything else (randint, choice, shuffle, sample, choices and the distributions) is pure Python in Lib/random.py, built on random(), getrandbits() and _randbelow()
Reproducibility
The docs guarantee only that random() keeps producing the same sequence for the same seed; the other algorithms may change between versions (sample() with counts= already differs between 3.12 and 3.13 for zero counts)
Floating point
gauss, normalvariate, lognormvariate, expovariate, vonmisesvariate, gammavariate, betavariate, paretovariate, weibullvariate and binomialvariate call math.log/exp/cos/sin/acos/log2 or float **, i.e. the platform C library, so a value can differ in its last digit between Windows, Linux and macOS. random, uniform, triangular, randint, randrange, choice, choices, sample, shuffle and getrandbits are exact on every platform. The demos compute correctly rounded library results; in a fuzz of 2,400 seeded calls per distribution they matched Linux CPython in at least 99.6 percent and Windows CPython in at least 97.8 percent of the draws (gauss differs most on Windows), so the demos round those values
Threads
The global functions and Random instances are thread-safe, but threads interleave draws, so seeded results are only reproducible single-threaded

FAQ

No. It is a pseudo-random generator (Mersenne Twister): every output follows deterministically from its internal state of 624 32-bit words. At import the state is seeded from os.urandom(), so unseeded runs differ, but the numbers are statistically random, not unpredictable.