Skip to content

How stet relates to similar libraries

Several Python libraries solve adjacent problems to stet. Understanding how they differ clarifies what stet is for and why it makes the design choices it does.

joblib.Memory

joblib.Memory is the most widely used tool in this space. It wraps a function so that the return value is persisted to disk on the first call and returned from the cache on subsequent identical calls: standard memoization, made durable across processes and restarts.

Because joblib.Memory stores return values, its storage is opaque: results live as pickle files in a nested directory structure not meant to be read by anything other than joblib itself. There is no way to open the cache in a spreadsheet, query it with SQL, or inspect it with standard tools. It also stores everything the function returns, which can mean large files for functions that return arrays or models.

It also has no concept of a key subset. The cache key is the full set of arguments; there is no way to say "these parameters define the experiment identity, but this one is just a computational setting". For research workflows where you want to vary convergence tolerances or iteration counts without invalidating cached results, this is a significant constraint.

stet is not trying to replace joblib.Memory; it is solving a different problem.

checkpointing

The checkpointing package (PyPI) is a decorator that caches return values as pickle files and skips re-execution for identical arguments, with configurable behaviour on errors. Its intent and API are close to joblib.Memory: persist outputs, skip re-computation.

The same differences apply. Storage is not human-readable or queryable, return values are always persisted, and there is no user-defined key subset. It adds some useful error-handling flexibility that joblib.Memory lacks, but the underlying model - cache the output, look it up on re-call - is the same.

checkpointer

checkpointer (PyPI) is a more sophisticated decorator focused on cache correctness. It can detect when the decorated function's source code or dependencies have changed and invalidate the cache accordingly. It also supports async functions and robust hashing of complex objects such as NumPy arrays and PyTorch tensors.

This solves a different problem. The question checkpointer answers is: is this cached result still valid given that the code may have changed? The question stet answers is: has this parameter combination been run before? For a researcher running a fixed parameter sweep across sessions, code-aware invalidation is not needed, and the overhead of hashing complex objects would add cost to every call.

memento (wickerlab)

memento is the closest in intent to stet. It is explicitly designed for researchers running expensive experiments over a parameter grid, with built-in parallelisation and result caching.

The key difference is that memento is workflow-prescriptive. You define your parameter grid upfront as a configuration object and pass it to Memento.run(), which handles iteration and parallelisation. This requires structuring your experiment around memento's API.

stet takes the opposite position: it is workflow-neutral. You decorate your function and loop over parameters however you already do: a for loop, a list comprehension, a call from a notebook cell, a parallel map. The decorator fits into existing code without restructuring it, and composes with whatever parallelisation approach you already use.