Skip to main content

py-cluster-api

CI

A Python library for submitting and monitoring jobs on HPC clusters. Supports running arbitrary executables (Nextflow pipelines, Python scripts, Java tools, etc.) on clusters and taking action when jobs complete via async callbacks.

Executors

  • Local Subprocess
  • IBM Platform LSF
  • We will accept PRs that implement and test additional executors (SLURM, etc.)

Features

  • Async-first — built on asyncio for non-blocking job submission and monitoring
  • Local executor — run jobs as local subprocesses for development and testing, including array jobs
  • Job monitoring — polls the scheduler and fires callbacks on job completion, failure, or cancellation
  • Job arrays — submit array jobs with per-element log files
  • Zombie detection — jobs that disappear from the scheduler are marked as failed
  • YAML config with profiles — Nextflow-style config with per-environment profiles
  • Callback chaining — register on_success, on_failure, or on_exit handlers on any job

Installation

Requires Python 3.10+.

pip install py-cluster-api

Or with Pixi:

pixi add --pypi py-cluster-api

Quick Start

Single Job

import asyncio
from cluster_api import create_executor, ResourceSpec, JobMonitor

async def main():
    executor = create_executor(profile="janelia_lsf")
    monitor = JobMonitor(executor)
    await monitor.start()

    job = await executor.submit(
        command="nextflow run nf-core/rnaseq --input samples.csv",
        name="rnaseq-run",
        resources=ResourceSpec(cpus=4, gpus=1, memory="32 GB", walltime="24:00", queue="long"),
        env={"NXF_WORK": "/scratch/work"},
    )
    job.on_success(lambda j: print(f"Done! Job {j.job_id}, peak mem: {j.max_mem}"))
    job.on_failure(lambda j: print(f"FAILED! Job {j.job_id}, exit={j.exit_code}"))

    await monitor.wait_for(job)
    await monitor.stop()

asyncio.run(main())

Job Array

async def run_array():
    executor = create_executor(profile="janelia_lsf")
    monitor = JobMonitor(executor)
    await monitor.start()

    job = await executor.submit_array(
        command="python process.py --index $LSB_JOBINDEX",
        name="batch-process",
        array_range=(1, 50),
        resources=ResourceSpec(cpus=1, memory="4 GB", walltime="01:00"),
    )
    job.on_exit(lambda j: print(f"Array finished: {j.job_id}"))

    await monitor.wait_for(job)
    await monitor.stop()

The array index environment variable depends on the executor: LSF uses $LSB_JOBINDEX, while the local executor uses $ARRAY_INDEX.

Reconnecting After Restart

If your process crashes or restarts, reconnect() rediscovers running jobs from the scheduler and resumes tracking them. Requires job_name_prefix to be set in config.

async def resume():
    executor = create_executor(profile="janelia_lsf")
    monitor = JobMonitor(executor)
    await monitor.start()

    recovered = await executor.reconnect()
    for job in recovered:
        print(f"Reconnected to {job.job_id} ({job.name}), status={job.status}")
        job.on_exit(lambda j: print(f"Job {j.job_id} finished: {j.status}"))

    if recovered:
        await monitor.wait_for(*recovered)
    await monitor.stop()

Local Testing

async def local_test():
    executor = create_executor(executor="local")
    monitor = JobMonitor(executor, poll_interval=1.0)
    await monitor.start()

    job = await executor.submit(command="echo hello world", name="test")
    job.on_success(lambda j: print("It worked!"))

    await monitor.wait_for(job, timeout=10.0)
    await monitor.stop()

Configuration

Configuration is loaded from YAML with optional profiles. The search order is:

  1. Explicit config_path argument
  2. $CLUSTER_API_CONFIG environment variable
  3. ./cluster_api.yaml
  4. ~/.config/cluster_api/config.yaml

Example cluster_api.yaml

executor: local
poll_interval: 10
job_name_prefix: "capi"

profiles:
  janelia_lsf:
    executor: lsf
    queue: normal
    gpus: 1
    memory: "8 GB"
    walltime: "04:00"
    script_prologue:
      - "module load java/11"

  local_dev:
    executor: local
    poll_interval: 2

Config Options

Option Default Description
executor "local" Backend: lsf or local
cpus None Default CPU count
gpus None Default GPU count
memory None Default memory (e.g. "8 GB")
walltime None Default wall time (e.g. "04:00")
queue None Default queue/partition
poll_interval 10.0 Seconds between status polls
job_name_prefix None Optional prefix prepended to job names. When set, polling filters by {prefix}-* and reconnect() is available; when unset, the user controls the full job name and polling queries all jobs
shebang "#!/bin/bash" Script shebang line
script_prologue [] Lines inserted before the command
script_epilogue [] Lines inserted after the command
extra_directives [] Additional scheduler directive lines appended verbatim to the script header (e.g. "#BSUB -P myproject")
directives_skip [] Substrings to filter out of directives
extra_args [] Extra CLI args appended to the submit command (e.g. bsub)
lsf_units "MB" LSF memory units (KB, MB, GB)
suppress_job_email true Set LSB_JOB_REPORT_MAIL=N
command_timeout 100.0 Timeout in seconds for scheduler commands
zombie_timeout_minutes 30.0 Mark jobs as failed if unseen for this long
completed_retention_minutes 10.0 Keep finished jobs in memory for this long

API Reference

See docs/API.md for the full API reference and error handling guide.

Development

See docs/Development.md for build instructions, testing, and release process.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_cluster_api-0.7.0.tar.gz (56.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_cluster_api-0.7.0-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file py_cluster_api-0.7.0.tar.gz.

File metadata

  • Download URL: py_cluster_api-0.7.0.tar.gz
  • Upload date:
  • Size: 56.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for py_cluster_api-0.7.0.tar.gz
Algorithm Hash digest
SHA256 1c3b22e9fad1010ec53e6751cf6cb21850dc86028733976219664126abc08981
MD5 8799a460a4e0c70f48fbb773c8f5f5f8
BLAKE2b-256 30d637e408bf0ee371ad4b7be5ed0c128dbbe4c7859541fa646e323a31ec1d27

See more details on using hashes here.

File details

Details for the file py_cluster_api-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: py_cluster_api-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 27.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for py_cluster_api-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8c0a4ebc8e51dd0a47c2a0defb23ef2b5459e95a81e36812fd4ed796f69b9875
MD5 c1570b1fe6fde6672fdb2ad59824be36
BLAKE2b-256 cd38b8fe01ead3f4ede2ad4cda9854d868d997f168cc79dcc5ae8ce060de4ed2

See more details on using hashes here.

Release history Release notifications | RSS feed

0.8.0

2 files

This release

0.7.0 This release

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page