Running from a CLI
The tools of GAIn run their task graphs from a command line through
TaskGraphCli. A script of your own can
do the same. TaskGraphCli adds the task graph options to an
argparse parser, and it runs a task graph by the parsed arguments.
This page describes the Python side of the options. The user page
Running in parallel describes what each option does.
Creating the arguments
TaskGraphCli.add_arguments adds the options
to a parser:
import argparse
from gain.task_graph import TaskGraphCli
parser = argparse.ArgumentParser()
TaskGraphCli.add_arguments(parser)
args = parser.parse_args()
Each option adds a key to the parsed arguments. Several keys do not have
the name of their option: --process-pool adds use_process_pool,
-N adds dask_cluster_name, -c adds
dask_cluster_config_file and -d adds task_status_dir. The
docstring of add_arguments lists every key. add_arguments adds no
-v. The commands list and status read verbose, so add -v
with VerbosityConfiguration.set_arguments.
Three keywords of add_arguments change the options:
use_commands=FalseRemoves the optional command
run,listorstatus. The script then always runs the graph.task_progress_mode=FalseRemoves
--forceand-d. The parsed arguments then have noforceand notask_status_dir.Warning
Pass the same
task_progress_modetoadd_argumentsand toprocess_graph.process_graphhas its own keyword. If you passtask_progress_mode=Falsetoadd_argumentsonly,process_graphstill builds aFileTaskCache, and the task cache writes its records into the current directory.default_task_status_dirSets the default of
-d, the task status directory. The default is./.task-progress. WithNone, a run without-dwrites the records of the task cache into the current directory.
The lifecycle
TaskGraphCli.process_graph takes the task
graph and the parsed arguments as keywords. It does these steps:
It prunes the graph to the task ids of
-t, and to the tasks that they depend on.It builds the task cache. With
task_progress_modetrue, the default, the task cache is aFileTaskCacheover the task status directory.For the command
run, the default, it creates the task executor withcreate_executor(). It runs the graph inside the context of the task executor, and it returns true when every task succeeds.For the commands
listandstatus, it prints the record type of each task and runs nothing. It returns true.
--force does not change the task cache. The task executor then runs
every task and writes every record again.
create_executor picks the task executor by the parsed arguments:
-j 1gives aSequentialExecutor.--process-poolwith-j Ngives aProcessPoolTaskExecutorwithNprocesses. Without-j, the pool has one process for each CPU.Every other case gives a
DaskExecutoron a named cluster, also a command line without-j.
-j 1 together with -N or -c fails an assert in
create_executor. A direct call of create_executor() without
keywords gives a SequentialExecutor.
A running example, part 3
Part 1, on the page Graphs, builds a graph that counts the N
bases of a reference genome. Part 2, on the page Task executors,
runs it from Python. Part 3 runs it from a command line.
The script has a main(argv) function. It adds the genomic context
options with context_providers_add_argparser_arguments and the task
graph options with add_arguments. Then it parses argv and builds
the genomic context. It takes the resource of the reference genome from
the genomic context, builds the graph of part 1, and calls
process_graph:
def main(argv: list[str] | None = None) -> bool:
"""Count the ``N`` bases of a reference genome from a command line."""
parser = argparse.ArgumentParser(
description="Count the N bases of a reference genome.")
context_providers_add_argparser_arguments(parser)
TaskGraphCli.add_arguments(parser)
args = parser.parse_args(argv)
context = build_cli_genomic_context(vars(args))
genome = context.get_reference_genome()
if genome is None:
parser.error("name the reference genome with -R")
graph, _ = build_n_count_graph(genome.resource)
return TaskGraphCli.process_graph(graph, **vars(args))
A command line names the GRR with --grr-directory <dir> or
-g <grr file>, and the reference genome with
-R <genome resource id>.
The return value of main is not an exit status: main returns
True when every task succeeds. A console script that calls
sys.exit(main()) exits with status 1 after a successful run. Map the
return value to an exit status in the function that the console script
calls:
def count_n() -> None:
"""Run ``main`` and exit with status 0 only when every task succeeds."""
sys.exit(0 if main(sys.argv[1:]) else 1)
In the commands below, count_n is a console script that calls the
function count_n. The first command runs the graph sequentially and
writes the records into the task status directory task-status:
count_n --grr-directory grr -R genome -j 1 -d task-status
After the run, the command status prints COMPUTED for each task:
count_n --grr-directory grr -R genome status -j 1 -d task-status
API
TaskGraphCli is defined in the module gain.task_graph.cli_tools.
It is also exported by the package gain.task_graph, as
gain.task_graph.TaskGraphCli.
Add the task graph options to a command line and run a task graph. |
|
|
Add the task graph options to a command line parser. |
|
Create the task executor that the parsed arguments choose. |
|
Run a task graph, or report its tasks, by the parsed arguments. |
- class TaskGraphCli[source]
Add the task graph options to a command line and run a task graph.
A tool calls
add_arguments()on its parser, and then callsprocess_graph()with its task graph and the parsed arguments as keywords. The page Running in parallel describes the options for the user.- static add_arguments(parser: ArgumentParser, *, task_progress_mode: bool = True, default_task_status_dir: str | None = './.task-progress', use_commands: bool = True) None[source]
Add the task graph options to a command line parser.
The options choose the task executor, the number of workers, the task status directory and the command. Pass the parsed arguments to
process_graph()with**vars(args). Several keys do not have the name of their option. The options add these keys:-jaddsjobs.--process-pooladdsuse_process_pool.-Naddsdask_cluster_name.-caddsdask_cluster_config_file.--task-log-diraddstask_log_dir.The optional command adds
command.-taddstask_ids.--keep-goingaddskeep_going.--fork-tasksaddsfork_tasks.--forceaddsforce.-daddstask_status_dir.
The function adds no
-v. The commandslistandstatusreadverbose, so add it withset_arguments().- Parameters:
parser (argparse.ArgumentParser) – The parser that gets the options.
task_progress_mode (bool) – When false, the parser gets no
--forceand no-d, and the parsed arguments have noforceand notask_status_dir. Pass the same value toprocess_graph(): it builds aFileTaskCacheby default whatever the parser holds, and withouttask_status_dirthe task cache writes its record files into the current directory.default_task_status_dir (str | None) – The default of
-d, the task status directory.Nonemeans that a run without-dwrites the record files of the task cache into the current directory.use_commands (bool) – When false, the parser gets no optional command
run,listorstatus, andprocess_graph()always runs the graph.
- static create_executor(task_cache: TaskCache | None = None, **kwargs: Any) TaskGraphExecutor[source]
Create the task executor that the parsed arguments choose.
With
jobsequal to 1, the function creates aSequentialExecutor. Otherwise, withuse_process_pooltrue, it creates aProcessPoolTaskExecutorwithjobsprocesses. In every other case, it creates aDaskExecutoron a named cluster.- Parameters:
task_cache (TaskCache | None) – The task cache of the task executor.
Nonemeans aNoTaskCache, which runs every task and records nothing.**kwargs –
The parsed arguments of
add_arguments(). The function reads these keys, and it passes all of them to the task executor too:jobsThe number of workers. A missing key means 1, so a call without keywords creates a
SequentialExecutor. A parsed command line always holdsjobs, with the valueNonewhen-jis absent, so a command line without-jcreates aDaskExecutor, or aProcessPoolTaskExecutorwith--process-pool.Nonemeans one process for each CPU for the process pool, and the default of the named cluster for dask.use_process_poolWhen true, and
jobsis not 1, the function creates aProcessPoolTaskExecutor.dask_cluster_nameThe named cluster of the
DaskExecutor.Nonemeans the default named cluster.dask_cluster_config_fileA cluster config file that describes the cluster of the
DaskExecutor.Nonemeans that the function usesdask_cluster_name.
- Returns:
The new task executor. Use it as a context manager, so that it releases its workers.
- Return type:
- Raises:
AssertionError – When
jobsis 1, oruse_process_poolis true, anddask_cluster_nameordask_cluster_config_fileis set. Also when bothdask_cluster_nameanddask_cluster_config_fileare set.
- static process_graph(task_graph: TaskGraph, *, task_progress_mode: bool = True, **kwargs: Any) bool[source]
Run a task graph, or report its tasks, by the parsed arguments.
The function prunes the graph to the tasks of
task_idsand builds the task cache withTaskCache.create. For the commandrun, it creates the task executor withcreate_executor()and runs the graph inside the context of the task executor. For the commandslistandstatus, it prints a table of the task ids and the record type of each task to the standard output, and it runs nothing.- Parameters:
task_graph (TaskGraph) – The task graph. A run consumes it.
task_progress_mode (bool) – When true, the task cache is a
FileTaskCacheovertask_status_dir. When false, it is aNoTaskCache. This keyword is separate from the keyword ofadd_arguments(), so pass the same value to both.**kwargs –
The parsed arguments of
add_arguments(). The function reads these keys, and it passes all of them tocreate_executor():commandrun,listorstatus.Nonemeansrun.task_idsThe ids of the tasks to keep. The graph keeps the tasks that they depend on too.
Nonemeans every task.task_status_dirThe task status directory of the
FileTaskCache.None, or a missing key, means the current directory.forceWhen true, the task executor runs every task and writes every record again. The task cache does not change.
keep_goingWhen true, the run continues after a failed task.
verboseWhen set and not 0, the commands
listandstatusprint the exception of each task with anERRORrecord.add_arguments()does not add this key. The-voption ofVerbosityConfiguration.set_argumentsadds it.
- Returns:
For
run, true when every task succeeds. Forlistandstatus, always true.- Return type:
bool
- Raises:
Exception – The error of the first failed task, for
runwithoutkeep_going.ValueError – When
commandis notrun,listorstatus, or when the graph has no task with one of thetask_ids.