Resume from where you stopped — automatically.
Zero dependencies · Python 3.9 – 3.13 · One line to use
key). Change any → new checkpoint file.checkpoint(value) — atomic write via tempfile + fsync + os.replace.SIGINT/SIGTERM, flushes the last checkpoint, exits with os._exit(130).Every Python developer has felt this:
Ctrl+C → start from zero.MemoryError at hour 6 → begin again.The usual answer: save checkpoints manually. You write try/except + pickle.dump, manage state files, handle corrupt saves… then forget one edge case, and it all falls apart anyway.
There has to be a better way.
from neverlose import resurrect, checkpoint
@resurrect
def train():
for epoch in range(1000):
loss = do_epoch(epoch)
checkpoint({"epoch": epoch, "loss": loss})
train()
That's it. Run it. Stop it. Crash it. Re-run the same file → it resumes automatically from the last epoch.
No try/except. No pickle.dump. No dependencies.
pip install neverlose
Python 3.9 → 3.13. Zero dependencies (standard library only).
🎯 Features
Feature What it means for you 🔁 Automatic resume Re-run the same file → picks up where it left off 💾 Atomic writes Power loss mid-save = no corrupt checkpoints, ever 🛑 Signal handling Catches Ctrl+C and SIGTERM, saves before exiting 🧬 Fingerprinting Detects code changes → avoids stale resumes 📦 Zero dependencies Only Python stdlib — works in air-gapped environments 🐍 Pure Python No C extensions, no compiled wheels
📖 Usage
🧠 Machine Learning Training
from neverlose import resurrect, checkpoint
@resurrect(key="gpt-small-v3")
def train_model():
model = build_model()
for epoch in range(100):
for batch in dataloader:
loss = train_step(model, batch)
checkpoint({"epoch": epoch, "loss": loss})
train_model()
Change key= when hyperparameters change → forces a fresh start.
from neverlose import resurrect, checkpoint
@resurrect(key="news-2026")
def scrape_all():
state = scrape_all.resume_state() or {"done": []}
done = set(state["done"])
for url in url_list:
if url in done:
continue
save(fetch(url), url)
done.add(url)
checkpoint({"done": list(done)})
scrape_all()
Ctrl+C mid-scrape → re-run → continues from the last URL.
from pathlib import Path
from neverlose import resurrect, checkpoint
@resurrect
def process(path):
files = list(Path(path).glob("*.parquet"))
state = process.resume_state() or {"i": 0}
for i, f in enumerate(files[state["i"] + 1:], start=state["i"] + 1):
transform(f)
checkpoint({"i": i, "total": len(files)})
process("/data/raw")
@resurrect(key="", keep=True, verbose=True)
def my_function():
...
Param Type Default Description key str "" Extra fingerprint ingredient — change to force a fresh start keep bool True Keep checkpoint file after success, or delete it verbose bool True Print resume/save messages to stderr
from neverlose import checkpoint, resume_state, reset
checkpoint({"step": 42}) # manual save inside a decorated function
resume_state(my_function) # → last saved value, or None
my_function.reset() # → delete checkpoint file
Environment variable: NEVERLOSE_DIR (default: ~/.neverlose)
❓ FAQ
pickle directly?pickle alone doesn't give you: (1) atomic writes — a crash mid-save can corrupt the file; (2) signal handling — Ctrl+C loses the last value; (3) fingerprinting — it doesn't know when your code changed. NeverLose wraps all three, plus a one-line decorator.
async def?Not in v1.0. v1.1 will support it. ⭐ if you want it sooner.
Yes — saves are guarded by threading.RLock. Each thread has its own store via threading.local.
multiprocessing?Partially — writes are atomic, but each process has its own fingerprint. First-class support lands in v1.2.
Small checkpoints: < 1ms on a modern SSD. Negligible compared to any real workload.
The function starts fresh — safely. No crash, no error.
By default, ~/.neverlose/ — keyed by BLAKE2b fingerprints. Override with NEVERLOSE_DIR=/path.
| Tool | Auto-resume | Zero deps | Any function | Atomic saves | Signal-safe |
|---|---|---|---|---|---|
pickle (manual) | ❌ | ✅ | ❌ | ❌ | ❌ |
joblib.Memory | ❌ | ❌ | ⚠️ | ❌ | ❌ |
dill | ❌ | ❌ | ⚠️ | ❌ | ❌ |
PyTorch Lightning | ✅ (PyTorch only) | ❌ | ❌ | ✅ | ✅ |
TensorFlow Checkpoint | ✅ (TF only) | ❌ | ❌ | ⚠️ | ⚠️ |
| NeverLose | ✅ | ✅ | ✅ | ✅ | ✅ |
async def support ← ⭐ to ship it fasterEvery PR is welcome — from typo fixes to full features.
git clone https://github.com/neverlose-io/neverlose.git
cd neverlose
pip install -e ".[dev]"
pytest -v
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
MIT © 2026 NeverLose IO — see LICENSE.
NeverLose is free and open source, built with zero funding and no corporate backing.
bc1qyw4mj8zjcutzpsd6skq87qv03t52804t6jkwte
0x009E3Cf6F51141DBF2EfEc33BC07c966651D0Da8
⚠️ Always verify the address before sending. Crypto transactions are irreversible.
It takes 2 seconds and helps other developers find it.
Python
100.0%
Resume from where you stopped — automatically.
Zero dependencies · Python 3.9 – 3.13 · One line to use
key). Change any → new checkpoint file.checkpoint(value) — atomic write via tempfile + fsync + os.replace.SIGINT/SIGTERM, flushes the last checkpoint, exits with os._exit(130).Every Python developer has felt this:
Ctrl+C → start from zero.MemoryError at hour 6 → begin again.The usual answer: save checkpoints manually. You write try/except + pickle.dump, manage state files, handle corrupt saves… then forget one edge case, and it all falls apart anyway.
There has to be a better way.
from neverlose import resurrect, checkpoint
@resurrect
def train():
for epoch in range(1000):
loss = do_epoch(epoch)
checkpoint({"epoch": epoch, "loss": loss})
train()
That's it. Run it. Stop it. Crash it. Re-run the same file → it resumes automatically from the last epoch.
No try/except. No pickle.dump. No dependencies.
pip install neverlose
Python 3.9 → 3.13. Zero dependencies (standard library only).
🎯 Features
Feature What it means for you 🔁 Automatic resume Re-run the same file → picks up where it left off 💾 Atomic writes Power loss mid-save = no corrupt checkpoints, ever 🛑 Signal handling Catches Ctrl+C and SIGTERM, saves before exiting 🧬 Fingerprinting Detects code changes → avoids stale resumes 📦 Zero dependencies Only Python stdlib — works in air-gapped environments 🐍 Pure Python No C extensions, no compiled wheels
📖 Usage
🧠 Machine Learning Training
from neverlose import resurrect, checkpoint
@resurrect(key="gpt-small-v3")
def train_model():
model = build_model()
for epoch in range(100):
for batch in dataloader:
loss = train_step(model, batch)
checkpoint({"epoch": epoch, "loss": loss})
train_model()
Change key= when hyperparameters change → forces a fresh start.
from neverlose import resurrect, checkpoint
@resurrect(key="news-2026")
def scrape_all():
state = scrape_all.resume_state() or {"done": []}
done = set(state["done"])
for url in url_list:
if url in done:
continue
save(fetch(url), url)
done.add(url)
checkpoint({"done": list(done)})
scrape_all()
Ctrl+C mid-scrape → re-run → continues from the last URL.
from pathlib import Path
from neverlose import resurrect, checkpoint
@resurrect
def process(path):
files = list(Path(path).glob("*.parquet"))
state = process.resume_state() or {"i": 0}
for i, f in enumerate(files[state["i"] + 1:], start=state["i"] + 1):
transform(f)
checkpoint({"i": i, "total": len(files)})
process("/data/raw")
@resurrect(key="", keep=True, verbose=True)
def my_function():
...
Param Type Default Description key str "" Extra fingerprint ingredient — change to force a fresh start keep bool True Keep checkpoint file after success, or delete it verbose bool True Print resume/save messages to stderr
from neverlose import checkpoint, resume_state, reset
checkpoint({"step": 42}) # manual save inside a decorated function
resume_state(my_function) # → last saved value, or None
my_function.reset() # → delete checkpoint file
Environment variable: NEVERLOSE_DIR (default: ~/.neverlose)
❓ FAQ
pickle directly?pickle alone doesn't give you: (1) atomic writes — a crash mid-save can corrupt the file; (2) signal handling — Ctrl+C loses the last value; (3) fingerprinting — it doesn't know when your code changed. NeverLose wraps all three, plus a one-line decorator.
async def?Not in v1.0. v1.1 will support it. ⭐ if you want it sooner.
Yes — saves are guarded by threading.RLock. Each thread has its own store via threading.local.
multiprocessing?Partially — writes are atomic, but each process has its own fingerprint. First-class support lands in v1.2.
Small checkpoints: < 1ms on a modern SSD. Negligible compared to any real workload.
The function starts fresh — safely. No crash, no error.
By default, ~/.neverlose/ — keyed by BLAKE2b fingerprints. Override with NEVERLOSE_DIR=/path.
| Tool | Auto-resume | Zero deps | Any function | Atomic saves | Signal-safe |
|---|---|---|---|---|---|
pickle (manual) | ❌ | ✅ | ❌ | ❌ | ❌ |
joblib.Memory | ❌ | ❌ | ⚠️ | ❌ | ❌ |
dill | ❌ | ❌ | ⚠️ | ❌ | ❌ |
PyTorch Lightning | ✅ (PyTorch only) | ❌ | ❌ | ✅ | ✅ |
TensorFlow Checkpoint | ✅ (TF only) | ❌ | ❌ | ⚠️ | ⚠️ |
| NeverLose | ✅ | ✅ | ✅ | ✅ | ✅ |
async def support ← ⭐ to ship it fasterEvery PR is welcome — from typo fixes to full features.
git clone https://github.com/neverlose-io/neverlose.git
cd neverlose
pip install -e ".[dev]"
pytest -v
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
MIT © 2026 NeverLose IO — see LICENSE.
NeverLose is free and open source, built with zero funding and no corporate backing.
bc1qyw4mj8zjcutzpsd6skq87qv03t52804t6jkwte
0x009E3Cf6F51141DBF2EfEc33BC07c966651D0Da8
⚠️ Always verify the address before sending. Crypto transactions are irreversible.
It takes 2 seconds and helps other developers find it.
Python
100.0%