Random numbers in Julia, generated by Python.
This package is for porting Python code, not for speed. It is not a faster random number generator — sampling calls into Python, so it is slower than native Julia RNGs. Its purpose is to help port existing Python libraries to Julia: because it reproduces Python's draws exactly, a translated routine can be validated against the original Python implementation value-for-value.
PythonRNGs exposes Python's random module and NumPy's two random APIs as
Julia AbstractRNG subtypes
through PythonCall.jl. For the same
seed, floats, integers, ranges, arrays, normals, permutations, and shuffles
reproduce the corresponding Python draws.
Three backends are provided:
| Backend | Python API |
|---|---|
PythonRandom |
random.Random |
NumPyRandomDefaultRNG |
numpy.random.default_rng (Generator) |
NumPyRandom |
legacy numpy.random.RandomState (np.random.seed / np.random.random) |
using Pkg
Pkg.add("PythonRNGs")Requires Julia 1.10+. The NumPy backends need a Python interpreter with NumPy, which PythonCall.jl manages via CondaPkg.jl:
using CondaPkg
CondaPkg.add("numpy")PythonRandom needs only the Python standard library.
using PythonRNGs, Random
rng = PythonRandom(1234) # wraps Python's random.Random(1234)
rand(rng) # 0.9664535356921388
default = NumPyRandomDefaultRNG(1234) # wraps numpy.random.default_rng(1234)
rand(default) # 0.9766997666981422
legacy = NumPyRandom(999) # wraps numpy.random.RandomState(999)
rand(legacy) # 0.8034280400796879All three are ordinary AbstractRNGs, so the usual Random entry points work:
rand(rng, Float64, 3) # 3 uniform values in [0, 1)
rand(rng, Float32)
rand(rng, 1:6) # uniform integer
rand(rng, Bool)
rand(rng, 10) # 10-element Vector{Float64} in [0, 1)
rand(rng, 1.0:0.5:2.0) # uniform element of a discrete float range
rand(rng, 'a':'z') # uniform character
rand(rng, Float64, 2, 2) # 2×2 matrix
rand!(rng, zeros(3)) # fill an existing array
randn(rng) # native standard normal draw
randn(rng, 2, 3) # normal matrix in C order
randperm(rng, 5) # Python permutation, shifted to 1:5
shuffle(rng, [1, 2, 3, 4]) # shuffled copy using the backend
shuffle!(rng, [1, 2, 3, 4]) # shuffle a vector in placeReseeding follows the Random interface:
Random.seed!(rng, 42) # reproduces the stream
Random.seed!(rng) # reseed from OS entropyusing Pkg
Pkg.test("PythonRNGs")- Home / guide
- Reproducibility — exact Python call for each draw, array order, and normal/permutation/shuffle behavior.
- API — backends,
supported interface, and
NotSupportedError.
Build the docs locally with:
$ julia --project=docs -e 'using Pkg; Pkg.instantiate()'
$ julia --project=docs -e 'using LiveServer; servedocs()'Developed with the assistance of DeepSeek v4.1 Flash.