Python basics#

The tutorials are written as Jupyter notebooks for interactive exploration, but everything in them also works as plain .py scripts. This page collects the one piece that differs between the two modes: waiting for a workflow to finish.

Waiting for workflow completion#

Agent.RunWorkflow launches Nextflow under nohup ... & on the agent side and returns as soon as the launch script exits. In a Jupyter notebook that is exactly what you want — you advance the next cell once the log output settles down. In a plain Python script the next line of code runs immediately, so calls like GetResultSource or CheckWorkflow will race past the still-running workflow and fail with errors such as:

FileNotFoundError: '/.../runs/<key>/_metasmith/logs.<ts>/main.log'
AssertionError: path [.../runs/<key>/results] does not exist

When the Nextflow process exits the agent writes a single sentinel line to agent.log inside the latest log directory of the task:

runs/<key>/_metasmith/logs.<latest>/agent.log
    ...
    run completed at [<timestamp>]

A small helper that polls for that sentinel is enough to convert any tutorial into a plain Python script:

wait_for_run helper#
 1import time
 2from pathlib import Path
 3
 4def wait_for_run(task_dir: Path, poll_s: float = 10.0, timeout: float | None = None) -> bool:
 5    """Block until the agent writes 'run completed at' to the latest agent.log."""
 6    deadline = None if timeout is None else time.monotonic() + timeout
 7    while deadline is None or time.monotonic() < deadline:
 8        logs = sorted((task_dir / "_metasmith").glob("logs.*"))
 9        if logs:
10            agent_log = logs[-1] / "agent.log"
11            if agent_log.exists() and "run completed at" in agent_log.read_text():
12                return True
13        time.sleep(poll_s)
14    return False

Use it around RunWorkflow:

Driving a tutorial from a plain Python script#
1smith.RunWorkflow(task, config_file=smith.GetNxfConfigPresets()["local"])
2
3task_dir = Path(agent_home.GetPath()) / "runs" / task.GetKey()
4if not wait_for_run(task_dir, poll_s=10):
5    raise RuntimeError("workflow did not complete in time")
6
7results_path = smith.GetResultSource(task).GetPath()
8results = DataInstanceLibrary.Load(results_path)

The helper works whether the agent home is local or remote — for remote agents the task_dir resolves to the mounted/synced view of the run directory exposed by the home Source.

Note

A first-class wait=True kwarg (or WaitForRun(task) method) on Agent.RunWorkflow is planned for a future release. Until then, use the helper above.