Nodus Python SDK
Run a training job on rented GPUs from Python. Nodus places the work on the cheapest capacity that fits, checkpoints it, and resumes it if the machine is taken back — so a fine-tune that would have died at hour six finishes.
import nodus
with nodus.Client() as client:
wl = client.run(command=["python", "train.py"], budget=20)
print(client.wait(wl.id).status)
Install
pip install nodus_compute
The distribution is nodus_compute; the import is nodus — the same split as
pip install scikit-learn and import sklearn.
Point it at your account
Two settings. Sign in at https://nodus.run/console/, create an API key — it is shown once — and the console's quickstart comes with both already filled in.
export NODUS_API_KEY=nk_live_…
export NODUS_BASE_URL=https://…
Or pass them directly: nodus.Client(api_key=…, base_url=…).
There is no built-in address. With neither setting the client raises
ConfigurationError before it opens a socket, naming what is missing — it does
not dial a guess and hand you a name-lookup error.
Running work
run() takes a flat brief and returns a Workload:
import nodus
with nodus.Client() as client:
wl = client.run(
image="python:3.11-slim",
command=["python", "train.py", "--epochs", "3"],
peak_memory_gb=24, # picks capacity that fits
expected_runtime_hours=6, # informs the estimate
budget=40, # a ceiling, not a reservation
)
done = client.wait(wl.id) # polls until the run is over
print(done.status, done.cost_now_usd)
Only command is required. Everything else narrows the search or bounds the
cost; omit budget and the run is uncapped.
Your image must be able to fetch a small binary — it needs curl, wget,
or python3 on the PATH. Most ML images have one. A bare ubuntu image has
none of them, and a machine that cannot fetch the runner is a machine you are
billed for while it does nothing.
Waiting
wait() polls until the workload is terminal and has no deadline of its
own. An 18-hour run is normal, and a client that gave up on one would not stop
it — the work would carry on and keep billing while your program believed it had
failed. A transient network failure does not end the wait either; only a
permanent one (a revoked key, an unknown workload) is raised.
Pass timeout_seconds= if you want a bound. It ends the waiting, not the run:
APITimeoutError is raised, the workload continues, and .cancel() is what
stops it.
Watching it
for event in client.stream_events(wl.id):
print(event.type, event.message)
print(client.logs(wl.id)) # the job's own stdout and stderr
print(wl.refresh().cost_now_usd) # charged plus what is accruing right now
Async
AsyncClient mirrors Client method for method:
async with nodus.AsyncClient() as client:
wl = await client.run(command=["python", "train.py"])
done = await client.wait(wl.id)
Errors
Every failure is a subclass of NodusError, so one except catches the lot:
| Raised | When |
|---|---|
ConfigurationError |
a setting is missing, before any request |
AuthenticationError |
the key is wrong or revoked |
ValidationError |
the brief was rejected, with the reason |
BudgetExceededError |
the run would pass your account's spend cap |
CapacityUnavailableError |
nothing in the market fits the brief |
NotFoundError |
no such workload |
RateLimitError |
too many requests; honours Retry-After |
APIConnectionError / APITimeoutError |
the network, not the API |
Command line
nodus run --command "python train.py" --budget 20
nodus status wl_…
nodus logs wl_…
Licence
Apache-2.0. See LICENSE.
Release files for nodus-compute 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nodus_compute-0.1.0.tar.gz | 50.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nodus_compute-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 83.1 kB
Release files / nodus_compute-0.1.0.tar.gz
| Download URL | nodus_compute-0.1.0.tar.gz |
|---|---|
| Size | 50.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
51748d10224a911010e670183e2962364d4594ad80bc7fda266b2fce04c68e63
|
|
BLAKE2b-256 checksum How to use checksums |
942f1f9b0d412bb6224b66cc59d5230b493ad1fb7631a67f1d303ecf667725e4
|
| 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 Sep 2, 2026.
Transparency logRelease files / nodus_compute-0.1.0-py3-none-any.whl
| Download URL | nodus_compute-0.1.0-py3-none-any.whl |
|---|---|
| Size | 32.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
011084e6b9b35dcd1805e5b21cb59c84935fe776c037d3282e995b5d8e3b9394
|
|
BLAKE2b-256 checksum How to use checksums |
9effcbe9f4e11a6e32252f09217a4ce9156cb2a20a40c70956648ac5c29ae756
|
| 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 Sep 2, 2026.
Transparency log