{"id":2778,"library":"spython","title":"spython: Singularity/Apptainer Python Client","description":"spython is a Python library that provides a programmatic interface for interacting with the Singularity (now Apptainer) container engine. It allows Python applications to execute Singularity commands, manage images, and run containers without directly calling the command-line interface. The current version is 0.3.15, and it maintains a somewhat active release cadence with several updates per year.","status":"active","version":"0.3.15","language":"en","source_language":"en","source_url":"https://github.com/singularityhub/singularity-cli","tags":["singularity","apptainer","container","hpc","cli-wrapper"],"install":[{"cmd":"pip install spython","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"symbol":"Client","correct":"from spython.main import Client"}],"quickstart":{"code":"from spython.main import Client\nimport os\n\n# Ensure Singularity/Apptainer is in your PATH\n# Example: Pull an image\nimage_name = \"alpine.sif\"\n\n# Pull an image\nprint(f\"Pulling image: docker://alpine:latest to {image_name}\")\nresult_pull = Client.pull(image=\"docker://alpine:latest\", pull_folder=os.getcwd(), pull_to=image_name)\nif result_pull.get('return_code') != 0:\n    print(f\"Error pulling image: {result_pull.get('stderr')}\")\nelse:\n    print(f\"Image pulled successfully: {result_pull.get('message')}\")\n\n    # Run a command inside the container\n    print(f\"Running 'ls -l /' in {image_name}\")\n    result_run = Client.run(image=image_name, command=\"ls -l /\")\n\n    if result_run.get('return_code') != 0:\n        print(f\"Error running command: {result_run.get('stderr')}\")\n    else:\n        print(\"Command output (stdout):\")\n        print(result_run.get('stdout'))\n\n    # Execute a command in the container with an instance\n    instance_name = \"my_alpine_instance\"\n    print(f\"Starting instance '{instance_name}' from {image_name}\")\n    result_instance_start = Client.instance_start(image=image_name, instance=instance_name, command=\"sleep 60\")\n    if result_instance_start.get('return_code') != 0:\n        print(f\"Error starting instance: {result_instance_start.get('stderr')}\")\n    else:\n        print(f\"Instance '{instance_name}' started. Executing 'cat /etc/os-release'...\")\n        result_exec = Client.execute(image=image_name, instance=instance_name, command=\"cat /etc/os-release\")\n        if result_exec.get('return_code') != 0:\n            print(f\"Error executing in instance: {result_exec.get('stderr')}\")\n        else:\n            print(\"Execution output (stdout):\")\n            print(result_exec.get('stdout'))\n\n        print(f\"Stopping instance '{instance_name}'\")\n        result_instance_stop = Client.instance_stop(instance=instance_name)\n        if result_instance_stop.get('return_code') != 0:\n            print(f\"Error stopping instance: {result_instance_stop.get('stderr')}\")\n        else:\n            print(f\"Instance '{instance_name}' stopped successfully.\")\n\n    # Clean up (optional): remove the pulled .sif file\n    if os.path.exists(image_name):\n        print(f\"Removing {image_name}\")\n        os.remove(image_name)","lang":"python","description":"This quickstart demonstrates how to pull a Singularity image, run a command inside it, start and execute a command within an instance, and then stop the instance. It highlights the importance of checking the return_code for command success."},"warnings":[{"fix":"Ensure Singularity/Apptainer is correctly installed and configured on your host system, and its binaries are discoverable via the PATH environment variable.","message":"spython acts as a wrapper for the Singularity (or Apptainer) command-line interface. For spython to function, the Singularity/Apptainer software must be installed on the system and its executable (e.g., `singularity` or `apptainer`) must be available in the system's PATH.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always check `result.get('return_code')` for a non-zero value to detect failures, and inspect `result.get('stderr')` for diagnostic information.","message":"All spython commands (e.g., `Client.pull`, `Client.run`, `Client.execute`) return a dictionary object. This dictionary contains crucial keys like `return_code`, `message`, `stdout`, and `stderr`. It is vital to check `return_code` for command success and `stderr` for any error messages, as `stdout` might be empty even on failure.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Manage instance names explicitly and avoid relying on `spython` to alter them. Ensure your instance start and stop commands use the exact instance names you intend.","message":"As of version `0.3.12`, `spython` explicitly changed behavior to prevent internal modification of instance names during operations. If your previous workflows implicitly relied on `spython` modifying or setting instance names, you will need to adjust.","severity":"breaking","affected_versions":">=0.3.12"},{"fix":"Use `os.path.abspath()` or provide full paths to `.sif` files when invoking `spython` commands.","message":"When working with local Singularity image files (.sif), particularly with commands like `Client.run` or `Client.execute`, ensure you provide the full, absolute path to the image. Relative paths can lead to `FileNotFoundError` if `spython`'s internal working directory differs from your script's execution context.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Review and test any workflows that programmatically create or convert Singularity recipes, specifically checking `WORKDIR` behavior, if upgrading from `spython < 0.3.0`.","message":"Version `0.3.0` introduced changes to how `WORKDIR` is matched when converting Dockerfile-like recipes to Singularity recipes. This might affect the interpretation of `WORKDIR` directives within containers if you are programmatically building or converting recipes using `spython` from versions prior to `0.3.0`.","severity":"breaking","affected_versions":">=0.3.0"}],"env_vars":null,"last_verified":"2026-04-10T00:00:00.000Z","next_check":"2026-07-09T00:00:00.000Z"}