Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions monai/apps/auto3dseg/auto_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

import os
import shutil
import subprocess
import warnings
from copy import deepcopy
from time import sleep
Expand All @@ -31,7 +30,7 @@
from monai.bundle import ConfigParser
from monai.transforms import SaveImage
from monai.utils import AlgoKeys, has_option, look_up_option, optional_import
from monai.utils.misc import check_kwargs_exist_in_class_init
from monai.utils.misc import check_kwargs_exist_in_class_init, run_cmd

logger = get_logger(module_name=__name__)

Expand Down Expand Up @@ -719,15 +718,15 @@ def _train_algo_in_nni(self, history: list[dict[str, Any]]) -> None:
logger.info(f"AutoRunner HPO is in dry-run mode. Please manually launch: {cmd}")
continue

subprocess.run(cmd.split(), check=True)
run_cmd(cmd.split(), check=True)

n_trainings = len(import_bundle_algo_history(self.work_dir, only_trained=True))
while n_trainings - last_total_tasks < max_trial:
sleep(1)
n_trainings = len(import_bundle_algo_history(self.work_dir, only_trained=True))

cmd = "nnictl stop --all"
subprocess.run(cmd.split(), check=True)
run_cmd(cmd.split(), check=True)
logger.info(f"NNI completes HPO on {name}")
last_total_tasks = n_trainings

Expand Down
4 changes: 2 additions & 2 deletions monai/apps/auto3dseg/bundle_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from monai.auto3dseg.utils import algo_to_pickle
from monai.bundle.config_parser import ConfigParser
from monai.config import PathLike
from monai.utils import ensure_tuple
from monai.utils import ensure_tuple, run_cmd
from monai.utils.enums import AlgoKeys

logger = get_logger(module_name=__name__)
Expand Down Expand Up @@ -243,7 +243,7 @@ def _run_cmd(self, cmd: str, devices_info: str = "") -> subprocess.CompletedProc

logger.info(f"Launching: {' '.join(cmd_list)}")

return subprocess.run(cmd_list, env=ps_environ, check=True)
return run_cmd(cmd_list, env=ps_environ, check=True)

def train(
self, train_params: None | dict = None, device_setting: None | dict = None
Expand Down
5 changes: 2 additions & 3 deletions monai/apps/auto3dseg/ensemble_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from __future__ import annotations

import os
import subprocess
from abc import ABC, abstractmethod
from collections.abc import Mapping, Sequence
from copy import deepcopy
Expand All @@ -33,7 +32,7 @@
from monai.transforms import MeanEnsemble, SaveImage, VoteEnsemble
from monai.utils import RankFilter, deprecated_arg
from monai.utils.enums import AlgoKeys
from monai.utils.misc import check_kwargs_exist_in_class_init, prob2class
from monai.utils.misc import check_kwargs_exist_in_class_init, prob2class, run_cmd
from monai.utils.module import look_up_option, optional_import

tqdm, has_tqdm = optional_import("tqdm", name="tqdm")
Expand Down Expand Up @@ -672,5 +671,5 @@ def _create_cmd(self) -> None:
cmd = f"{cmd} -m {base_cmd}"
cmd_list = cmd.split()

_ = subprocess.run(cmd_list, env=ps_environ, check=True)
run_cmd(cmd_list, env=ps_environ, check=True)
return
2 changes: 2 additions & 0 deletions monai/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
MAX_SEED,
ImageMetaKey,
MONAIEnvVars,
check_kwargs_exist_in_class_init,
check_parent_dir,
copy_to_device,
ensure_tuple,
Expand All @@ -84,6 +85,7 @@
path_to_uri,
pprint_edges,
progress_bar,
run_cmd,
sample_slices,
save_obj,
set_determinism,
Expand Down
28 changes: 28 additions & 0 deletions monai/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import pprint
import random
import shutil
import subprocess
import tempfile
import types
import warnings
Expand Down Expand Up @@ -73,6 +74,7 @@
"CheckKeyDuplicatesYamlLoader",
"ConvertUnits",
"check_kwargs_exist_in_class_init",
"run_cmd",
]

_seed = None
Expand Down Expand Up @@ -821,3 +823,29 @@ def check_kwargs_exist_in_class_init(cls, kwargs):
extra_kwargs = input_kwargs - init_params

return extra_kwargs == set(), extra_kwargs


def run_cmd(cmd_list: list[str], **kwargs: Any) -> subprocess.CompletedProcess:
"""
Run a command by using ``subprocess.run`` with capture_output=True and stderr=subprocess.STDOUT
so that the raise exception will have that information. The argument `capture_output` can be set explicitly
if desired, but will be overriden with the debug status from the variable.

Args:
cmd_list: a list of strings describing the command to run.
kwargs: keyword arguments supported by the ``subprocess.run`` method.

Returns:
a CompletedProcess instance after the command completes.
"""
debug = MONAIEnvVars.debug()
kwargs["capture_output"] = kwargs.get("capture_output", debug)

try:
return subprocess.run(cmd_list, **kwargs)
except subprocess.CalledProcessError as e:
if not debug:
raise
output = repr(e.stdout).replace("\\n", "\n").replace("\\t", "\t")
errors = repr(e.stderr).replace("\\n", "\n").replace("\\t", "\t")
Comment thread
mingxin-zheng marked this conversation as resolved.
Outdated
raise RuntimeError(f"subprocess call error {e.returncode}: {errors}, {output}.") from e
Comment thread
wyli marked this conversation as resolved.