Running Python

There is no separate Python preset class — you run Python with the same Machine API as everything else. Use run(image, command) to execute Python in a container image, or writeFile a script and run it. TypeScript is async; Python is synchronous.

Run Python code

The quickest way is run with an inline python -c command against a Python image:

import { Machine } from 'smolmachines';

const machine = await Machine.create({ name: 'python-env' });
try {
  const result = await machine.run(
    'python:3.12-alpine',
    ['python', '-c', 'import sys; print(sys.version); print(2 ** 10)']
  );
  console.log(result.stdout);
} finally {
  await machine.delete();
}
from smol import Machine, MachineConfig

with Machine.create(MachineConfig(name="python-env")) as machine:
    result = machine.run(
        "python:3.12-alpine",
        ["python", "-c", "import sys; print(sys.version); print(2 ** 10)"],
    )
    print(result.stdout)

Run a Python script

For anything longer than a one-liner, write the script into the machine with writeFile / write_file, then run it:

const machine = await Machine.create({ name: 'python-script' });
try {
  await machine.writeFile('/workspace/main.py', `
import json

data = [1, 2, 3, 4, 5]
print(json.dumps({"sum": sum(data), "max": max(data)}))
`);

  const result = await machine.run(
    'python:3.12-alpine',
    ['python', '/workspace/main.py']
  );
  console.log(JSON.parse(result.stdout));
} finally {
  await machine.delete();
}
with Machine.create(MachineConfig(name="python-script")) as machine:
    machine.write_file("/workspace/main.py", """
import json

data = [1, 2, 3, 4, 5]
print(json.dumps({"sum": sum(data), "max": max(data)}))
""")

    result = machine.run("python:3.12-alpine", ["python", "/workspace/main.py"])
    print(result.stdout)

Installing packages

Install with pip in the same container, then run your code — chain both in one run via sh -c, or use execStream to watch a long install live:

const result = await machine.run('python:3.12-alpine', [
  'sh', '-c',
  'pip install --quiet requests && python -c "import requests; print(requests.__version__)"'
]);
console.log(result.stdout);
result = machine.run("python:3.12-alpine", [
    "sh", "-c",
    "pip install --quiet requests && python -c \"import requests; print(requests.__version__)\"",
])
print(result.stdout)

To stream install output as it happens, use execStream / exec_stream:

for await (const ev of machine.execStream(['pip', 'install', 'numpy'])) {
  if (ev.kind === 'stdout' || ev.kind === 'stderr') process.stdout.write(ev.data);
}
for ev in machine.exec_stream(["pip", "install", "numpy"]):
    if ev["kind"] in ("stdout", "stderr"):
        print(ev["data"], end="")

Custom Python image

For reproducible environments, run your own prebuilt image instead of installing at runtime:

const result = await machine.run(
  'myregistry/python-ml:latest',
  ['python', '-c', 'import torch; print(torch.__version__)']
);

Data science example

Mount a data directory and run a pandas job. Files written under the mount are visible on the host:

const machine = await Machine.create({
  name: 'data-science',
  resources: { cpus: 2, memoryMb: 2048 },
  mounts: [{ source: '/data', target: '/data' }]
});

try {
  await machine.writeFile('/workspace/analyze.py', `
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('/data/sales.csv')
summary = df.groupby('region')['revenue'].sum()
print(summary)

summary.plot(kind='bar')
plt.savefig('/data/chart.png')
print('Chart saved to /data/chart.png')
`);

  const result = await machine.run('python:3.12-alpine', [
    'sh', '-c',
    'pip install --quiet pandas matplotlib && python /workspace/analyze.py'
  ]);
  console.log(result.stdout);
} finally {
  await machine.delete();
}