This release is a pre-release and may not be stable for production use.
rand-engine
Synthetic data, very fast, from a declarative spec — for batch and streaming, on any platform.
- Sink-agnostic: feed Kafka and other queues, data lakes and object storage, files, databases or Spark.
- NumPy-fast: the core is Python + NumPy (
DataGenerator); Spark is supported (SparkGenerator), never required. - Faker composes on top: build a small realistic pool with Faker, sample millions of rows from it at NumPy speed.
- Related tables:
pkandfkcolumns keep keys consistent across tables, batches, streams and files.
Install
pip install rand-engine
Quickstart
A spec maps each column to a method and its kwargs.
from rand_engine import DataGenerator
spec = {
"user_id": {"method": "int_zfilled", "kwargs": {"length": 8}},
"age": {"method": "integers", "kwargs": {"min": 18, "max": 80}},
"plan": {"method": "distincts_prop", "kwargs": {"distincts": {"free": 8, "pro": 2}}},
"signup": {"method": "dates", "kwargs": {"start": "2024-01-01", "end": "2024-12-31"}},
}
df = DataGenerator(spec, seed=42).size(1_000).get_df()
assert df.shape == (1_000, 4) and df["age"].between(18, 80).all()
Seeded reproducibility
The seed is per generator: each DataGenerator owns its own NumPy Generator (PCG64), so the
caller's NumPy global state is never read or reset. The same spec, seed and size give the same
frame. Values differ from 0.6.x, which drew from the global NumPy seed.
import numpy as np
np.random.seed(0)
state = np.random.get_state()[1].copy()
a = DataGenerator(spec, seed=7).size(100).get_df()
b = DataGenerator(spec, seed=7).size(100).get_df()
assert a.equals(b)
assert (np.random.get_state()[1] == state).all()
Faker pools at scale
Install the optional Faker dependency with pip install faker before running this example.
Faker is slow per value; draw a pool once and let rand-engine sample it.
from faker import Faker
fake = Faker()
Faker.seed(0)
names = [fake.name() for _ in range(200)]
people = DataGenerator({"name": {"method": "distincts", "kwargs": {"distincts": names}}}, seed=1).size(10_000).get_df()
assert people["name"].isin(names).all()
Related tables
Give the child's fk the parent's pk spec and size: every child key exists in the parent.
customer_pk = {"method": "pk", "kwargs": {"start": 1, "format": "C{:05d}"}}
customers = DataGenerator({"customer_id": customer_pk}, seed=1).size(500).get_df()
orders = DataGenerator({
"order_id": {"method": "pk", "kwargs": {"start": 1}},
"customer_id": {"method": "fk", "kwargs": {"parent": customer_pk, "parent_size": 500}},
}, seed=2).size(2_000).get_df()
assert customers["customer_id"].is_unique
assert set(orders["customer_id"]) <= set(customers["customer_id"])
Streams and files
stream_dict yields records forever at a bounded rate; write writes csv, json or parquet.
from itertools import islice
import pandas as pd
events = DataGenerator({"event_id": {"method": "pk", "kwargs": {"start": 1}}}, seed=1).size(10)
records = list(islice(events.stream_dict(min_throughput=500, max_throughput=1000), 5))
assert [r["event_id"] for r in records] == [1, 2, 3, 4, 5]
orders_gen = DataGenerator({"order_id": {"method": "pk", "kwargs": {"start": 1}}}, seed=1).size(1_000)
orders_gen.write.format("parquet").save("out/orders.parquet")
assert len(pd.read_parquet("out/orders.parquet")) == 1_000
Learn more
- DataGenerator: methods, seeds, streams.
- SparkGenerator: the same spec as a Spark DataFrame.
- Writing files:
writeandwriteStream, formats and options. - Keys:
pkandfkin depth. - Recipes: Faker pools, queues, parquet lakes, related tables.
- Benchmarks: rows/µs per method, measured in CI.
- Changelog: the 0.7.0 breaking changes.
- License: MIT.
Metadata
Release files for rand-engine 0.7.0rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rand_engine-0.7.0rc1.tar.gz | 42.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rand_engine-0.7.0rc1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 94.5 kB
Release files / rand_engine-0.7.0rc1.tar.gz
| Download URL | rand_engine-0.7.0rc1.tar.gz |
|---|---|
| Size | 42.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dfd2d9e9cada2c507c93ea510319b260585ad38055f96ec3ba59ae2481d2c5b4
|
|
BLAKE2b-256 checksum How to use checksums |
ace4d83630cf22a9ee952f83cea3936355f0deaa163ee9be5957ea7581ad37ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / rand_engine-0.7.0rc1-py3-none-any.whl
| Download URL | rand_engine-0.7.0rc1-py3-none-any.whl |
|---|---|
| Size | 51.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f0ed498b5b17a39fe3771f820b9dbd441c832affbb79d657f2b1b1433493d96b
|
|
BLAKE2b-256 checksum How to use checksums |
c7d7be4ac67e83329f53ac103e0f24ddd29510b0f41447754b3a3bf223be1621
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency log