Skip to content

Process module

The Process module provides a friendlier wrapper around subprocess.run.

String argument processing

from boldi.proc import run

run("echo 'Hello, World!'")
# Prints: Hello, World!
# Returns: CompletedProcess(args=['echo', 'Hello, World!'], returncode=0)

As you can see from the return value, echo was invoked with one argument: "Hello, World!". Simple string args passed to run() are processed via shlex.split.

Quoting arguments

Another way to quote arguments is to pass them inside a list.

from boldi.proc import run

run("echo", ["Hello, World!"])
# Prints: Hello, World!
# Returns: CompletedProcess(args=['echo', 'Hello, World!'], returncode=0)

This example is equivalent to the previous one.

Think of the [ list ] as a way of quoting arguments, telling the run() function not to further process those arguments.

Other positional arguments

Other types of positional arguments are converted to str and directly passed as arguments to the subprocess.

This is useful for passing numbers or pathlib.Path objects that may contain spaces.

Keyword arguments

Keyword arguments are the same as in subprocess.run except that a few default values are different.

See the boldi.proc.run API docs for details.

Running Python scripts

The run_py() function is a shortcut for running Python scripts. It correctly selects the current Python interpreter (sys.executable) as the first argument. All other arguments are the same as in run().

Install

Boldi's Process module is distributed as the boldi-proc Python package, thus to install it, run:

pip install boldi-proc

...or add "boldi-proc" as a dependency to your project.

Import

Import the module like so:

import boldi.proc
# or:
from boldi.proc import run, run_py

API

boldi.proc

RunArgs

Bases: TypedDict

Arguments to subprocess.run or subprocess.Popen.

Source code in pkg/boldi-proc/boldi/proc.py
class RunArgs(TypedDict, total=False):
    """
    Arguments to [`subprocess.run`][] or [`subprocess.Popen`][].
    """

    bufsize: int
    capture_output: bool
    check: bool
    close_fds: bool
    cwd: Path
    encoding: str
    env: Mapping[str, str]
    errors: Any
    extra_groups: Iterable[str | int]
    group: str | int
    input: str | None
    pipesize: int
    preexec_fn: Callable[..., Any]
    process_group: int
    shell: bool
    startupinfo: Any
    stderr: IO | int
    stdin: IO | int
    stdout: IO | int
    text: bool
    timeout: float
    umask: int
    universal_newlines: bool
    user: str | int
bufsize: int
capture_output: bool
check: bool
close_fds: bool
cwd: Path
encoding: str
env: Mapping[str, str]
errors: Any
extra_groups: Iterable[str | int]
group: str | int
input: str | None
pipesize: int
preexec_fn: Callable[..., Any]
process_group: int
shell: bool
startupinfo: Any
stderr: IO | int
stdin: IO | int
stdout: IO | int
text: bool
timeout: float
umask: int
universal_newlines: bool
user: str | int

args_iter(*args: Union[str, List[Any]]) -> Iterable[str]

Split mixed and/or quoted command line arguments into a simple list of arguments.

Parameters:

  • args (Union[str, List[Any]], default: () ) –

    Command line arguments, provided as positional arguments. Each argument is processed differently depending on its type. Strings are split using shlex.split into further arguments. Lists are replaced by their contents (each item converted to a string). Other types are converted to strings using str.

Returns:

  • Iterable[str]

    A flat list of command line arguments.

Examples:

Common use cases:

result = ["prog", "-a=b", "d e", "f"]
assert list(args_iter("prog -a=b 'd e' f")) == result
assert list(args_iter("prog -a=b", ["d e"], "f")) == result

Any argument can be given either as a string or a list, and they can be combined arbitrarily:

result = ["prog", "-a=b", "d e", "f"]
assert list(args_iter("prog -a=b", "'d e' f")) == result
assert list(args_iter("prog", "-a=b", '"d e"', "f")) == result
assert list(args_iter(["prog", "-a=b", "d e", "f"])) == result
Source code in pkg/boldi-proc/boldi/proc.py
def args_iter(*args: Union[str, List[Any]]) -> Iterable[str]:
    """
    Split mixed and/or quoted command line arguments into a simple list of arguments.

    Args:
        args: Command line arguments, provided as positional arguments.
            Each argument is processed differently depending on its type.
            Strings are split using [`shlex.split`][] into further arguments.
            Lists are replaced by their contents (each item converted to a string).
            Other types are converted to strings using [`str`][].

    Returns:
        A flat list of command line arguments.

    Examples:
        Common use cases:

        ```py
        result = ["prog", "-a=b", "d e", "f"]
        assert list(args_iter("prog -a=b 'd e' f")) == result
        assert list(args_iter("prog -a=b", ["d e"], "f")) == result
        ```

        Any argument can be given either as a string or a list,
        and they can be combined arbitrarily:

        ```py
        result = ["prog", "-a=b", "d e", "f"]
        assert list(args_iter("prog -a=b", "'d e' f")) == result
        assert list(args_iter("prog", "-a=b", '"d e"', "f")) == result
        assert list(args_iter(["prog", "-a=b", "d e", "f"])) == result
        ```
    """
    for arg in args:
        if isinstance(arg, str):
            yield from shlex.split(arg)
        elif isinstance(arg, list):
            yield from (str(sub_arg) for sub_arg in arg)
        else:
            yield str(arg)

run(*args: Union[str, List[Any]], **kwargs: Unpack[RunArgs]) -> subprocess.CompletedProcess

Run a subprocess using the provided command line arguments and updated defaults.

Parameters:

  • args (Union[str, List[Any]], default: () ) –

    Command line arguments, provided as positional arguments. As defined in args_iter.

  • kwargs (Unpack[RunArgs], default: {} ) –

    Arguments to subprocess.run. Defaults to check=True, text=True, and connecting to sys.{stdin, stdout, stderr}, unless otherwise set by the caller.

Returns:

Source code in pkg/boldi-proc/boldi/proc.py
def run(*args: Union[str, List[Any]], **kwargs: Unpack[RunArgs]) -> subprocess.CompletedProcess:
    """
    Run a subprocess using the provided command line arguments and updated defaults.

    Args:
        args: Command line arguments, provided as positional arguments.
            As defined in [`args_iter`][boldi.proc.args_iter].
        kwargs: Arguments to [`subprocess.run`][].
            Defaults to `check=True`, `text=True`, and connecting to `sys.{stdin, stdout, stderr}`,
            unless otherwise set by the caller.

    Returns:
        Completed process object.
    """
    kwargs.setdefault("check", True)
    kwargs.setdefault("text", True)
    if not kwargs.get("capture_output"):
        kwargs.setdefault("stdin", sys.stdin)
        kwargs.setdefault("stdout", sys.stdout)
        kwargs.setdefault("stderr", sys.stderr)
    args_list = list(args_iter(*args))
    return subprocess.run(args_list, **kwargs)

run_py(*args: Union[str, List[Any]], **kwargs: Unpack[RunArgs]) -> subprocess.CompletedProcess

Run a subprocess using the current Python interpreter, the provided command line arguments and updated defaults.

Parameters:

Returns:

Source code in pkg/boldi-proc/boldi/proc.py
def run_py(*args: Union[str, List[Any]], **kwargs: Unpack[RunArgs]) -> subprocess.CompletedProcess:
    """
    Run a subprocess using the current Python interpreter, the provided command line arguments and updated defaults.

    Args:
        args: Command line arguments, provided as positional arguments.
            As defined in [`args_iter`][boldi.proc.args_iter].
        kwargs: Arguments to [`subprocess.run`][]. As defined in [`run`][boldi.proc.run].

    Returns:
        Completed process object.
    """
    return run([sys.executable], *args, **kwargs)