random module
Monty’s random uses CPython’s MT19937 core, ported from Modules/_randommodule.c, with the method bodies of
Lib/random.py ported on top.
A seeded generator produces CPython 3.14’s sequence: random.seed(42) gives the same random(), randint(),
choice(), shuffle(), sample() and choices() results as CPython, and the same distribution values on the same
platform (see the note on floats below).
- Module functions:
random,seed,getstate,setstate,getrandbits,randbytes,randrange,randint,choice,choices,shuffle,sample,uniform,triangular,normalvariate,gauss,lognormvariate,expovariate,vonmisesvariate,gammavariate,betavariate,paretovariate,weibullvariate,binomialvariate. random.Random(x=None)instances with the same methods and an independent state, plusinstance.VERSION.
An unseeded generator seeds itself on its first draw from the session’s random_start
(os_policy on checkout() in the bindings, OsPolicy::random_start in Rust):
'system'reads 2496 bytes of OS entropy, the 624 32-bit words of an MT19937 state vector. If entropy is unavailable, the run ends with an uncatchableOSError: OS entropy source unavailable: <reason>. CPython instead falls back to the time and process ID.- A configured seed initializes the module generator as
random.seed(s)would. UnseededRandom()instances and calls toseed(None)receive successive states derived from that seed. These states are reproducible and distinct; CPython reads fresh entropy for each. See entropy configuration and the seed type restrictions below. 'call_host'requests 2496 bytes throughos.urandomon the first draw or aseed(None)call. The bytes seed the generator as CPython’sseed(None)would; fixed bytes make runs reproducible. A reply with another type or length raisesRuntimeError. An unanswered request raisesRuntimeError: 'os.urandom' is not supported in this environmentin the pools, orNotImplementedErrorin non-suspending Rust execution.
random.seed(s) with an explicit value overrides the session policy.
random.seed() and random.seed(None) use that policy; getstate() also seeds a never-seeded generator first.
The module-level generator is session state like the globals: a seed set in one feed_run applies to the next, and
it is included in a dump, as is the session’s random_start.
Randominstances do not convert to host values. Returning aRandominstance,random.Randomortype(rng)to the host producesunstable::MontyNode::Reprin Rust and a string in Python. Return the generated values orrng.getstate()instead.- No
SystemRandom, andrandom.Randomcannot be subclassed (Monty has no class inheritance, see classes.md).random.Random.VERSIONon the class raisesAttributeError; on an instance it is3. Instances have nogauss_nextattribute. - Copying an unseeded generator gives two independent streams.
copy.copy(rng)andcopy.deepcopy(rng)rebuild a generator at the same point in the same sequence, but one that has never been seeded has no state to carry, so each copy takes its own first state on its first draw. CPython seeds at construction, so its copies agree. See copy.md. - Instance methods must be called directly, as on other native objects such as
re.Pattern.rng.random()works, butdraw = rng.randomandgetattr(rng, 'random')raiseAttributeError. Module functions can be stored and passed as callbacks:draw = random.randomworks. - Integer ranges are 64-bit.
randrange,randint,choiceandsampleraiseOverflowError: Python int too large to convert to C ssize_tfor bounds outsidei64; CPython accepts any int.seed(big_int)accepts any int, as in CPython.getrandbits(k)raisesOverflowError: Python int too large for C uint64_tfromk >= 2**63, where CPython accepts up to2**64and then fails to allocate;randbytes(n)raises it fromn >= 2**61in both. The sum ofsample(counts=...)must also fit in a signed 64-bit integer. - Seeds.
seed(x)acceptsNone,int,float,strandbytes; there is nobytearray.seed(float('nan'))seeds from0, where CPython hashes the object’s address. Astr/bytesseed with aversionother than1or2is hashed with Monty’s own string hash, where CPython’s hash is randomized per process. - The distributions convert their arguments to float, so a non-number raises
TypeError: must be real number, not strwhere CPython reports the arithmetic that failed (unsupported operand type(s) for -).binomialvariate(n, p)requires an intn. sampleacceptslist,tuple,str,bytes,rangeanddequepopulations only (CPython accepts anycollections.abc.Sequence).kand eachcountsentry must be ints, sosample(x, 1.5)raises'float' object cannot be interpreted as an integerinstead of CPython’s sequence-multiplication error.choicesaccumulatesweightsas floats, so int weights above2**53lose precision;cum_weightsmay be any iterable of numbers.setstateaccepts version 3 and version 2 state tuples; the third element (gauss_next) must beNoneor afloat,intorbool, and is stored as a float, where CPython stores any object. A state word in2**63..2**64is truncated to 32 bits as on 64-bit CPython; CPython on Windows raisesOverflowErrorfor it.- Argument errors on an unseeded generator are raised after it is seeded. Whether a draw needs a first state is
decided before its arguments are parsed, so
random.randint('a')on a never-seeded generator seeds it and only then raises itsTypeError; under a session seed the draw that follows is the second, not the first. CPython seeds at import, so it raises without reading entropy. - Float results match CPython on the same platform. The distributions call the platform’s
log,exp,sin,cosandpow, as CPython does, so values can differ in the last bits between operating systems.binomialvariateuses thelibmcrate’slgammawhere CPython has its own implementation, which can change the outcome of a borderline acceptance test. Float-power overflow messages use glibc’s(34, 'Numerical result out of range')on every platform. - Arity errors do not count
self.random.seed(1, 2, 3)reportstakes from 0 to 2 positional arguments but 3 were givenwhere CPython, calling a bound method, saysfrom 1 to 3 ... but 4.getstate(1)reportstakes no arguments (1 given). randrange(start, None, 1)treats an explicit1step as the default, as CPython does through small-int identity, so it succeeds;Trueis not1there and raisesMissing a non-None stop argumentin both.