37. process — Executing external commands.

This module provides some functions for executing external commands in a subprocess. They are based on the standard Python subprocess module, but provide some practical enhancements.

Contents:

  • DoneProcess is a class to hold information about a terminated process.

  • run() runs a command in a subprocess and waits for it to finish. Returns a DoneProcess about the outcome.

  • start() starts a subprocess and does not wait for it. Returns a subprocess.Popen instance that can be used to communicate with the process.

This module can be used independently from pyFormex.

37.1. Classes defined in module process

class process.DoneProcess(args, returncode, *, failed=False, timedout=False, **kargs)[source]

A class to return the outcome of a subprocess.

This is a subclass of subprocess.CompletedProcess with some extra attributes.

args

The args that were used to create the subprocess.

Type:

str or sequence of arguments

returncode

The exit code of the subprocess. Typical a 0 means it ran succesfully. If the subprocess fails to start, the value is 127. Other non-zero values can be returned by the child process to flag some error condition.

Type:

int

stdout

The standard output captured from the child process.

Type:

str or bytes or None

stderr

The error output captured from the child process.

Type:

str or bytes or None

failed

True if the child process failed to start, e.g. due to a non-existing or non-loadable executable. The returncode will be 127 in this case.

Type:

bool

timedout

True if the child process exited due to a timeout condition.

Type:

bool

37.2. Functions defined in module process

process.run(args, *, input=None, capture_output=True, timeout=None, wait=True, **kargs)[source]

Execute a command through the operating system.

Run an external command in a subprocess, waiting for its termination or not. This is similar to Python3’s subprocess.run(), but provides the following enhancements:

  • If shell is True, and no executable is provided, the shell will default to the value in the user’s SHELL environment variable, and if that isn’t set, to ‘/bin/sh’.

  • If a string is passed as args and shell is False, the string is automatically tokenized into an args list.

  • If no stdout nor stderr are specified, the output of the command is captured by default.

  • The encoding is set to ‘utf-8’ by default, so that stdout and stderr are returned as strings.

  • stdin, stdout and stderr can be file names. They will be replaced with the opened files (in mode ‘r’ for stdin, ‘w’ for the others).

  • Exceptions are captured by default and can be detected from the return value.

  • A wait parameter allows the same function to be used to just start a subprocess and not wait for its outcome.

Only the new and changed parameters are described hereafter. Except for the first (args), all parameters should be specified by keyword. For more parameters, see subprocess.run.

Parameters:
  • args (str or list of str.) –

    If a string is provided, it is the command as it should be entered in a shell. If it is a list, args[0] is the executable to run and the remainder of args are the arguments to be passed to it.

    If a string is provided and shell is False (default), the string is split into an args list using shlex.split().

  • capture_output (bool) – If True (default), both stdout and stderr are captured and available from the returned DoneProcess. Specifying a value for any of stdout or stderr values will however override the capture_output setting.

  • shell (bool) – Default is False. If True, the command will be run in a new shell. The args argument should be a string in this case. Note that this uses more resources, may cause a problem in killing the subprocess and and may pose a security risk. Unless you need some shell functionality (like parameter expansion, compound commands, pipes), the advised way to execute a command is to use the default False.

  • executable (str) – The full path name of the program to be executed. This can be used to specify the real executable if the program specified in args is not in your PATH, or, when shell is True, if you want to use a shell other than the default: the value of the ‘SHELL’ environment variable, and if that is not set, ‘/bin/sh/’.

  • encoding (str) – The encoding for the returned stdout and stderr. The default is ‘utf-8’, making the returned values Python3 str types. Specifying encoding=None will return bytes. Another encoding may be specified if needed.

  • input (str) – If provided, passes the provided string as stdin to the started process. Only available with wait=True.

  • timeout (int) – If provided, this is the maximum number of seconds the process is allowed to run. After this time the Process will be killed.

  • check (bool) – Default is False. If True, an exception will be raised when the command did not terminate normally: a non-zero returncode, a timeout condition or a failure to start the executable. With the default, these conditions are captured and reported in the return value.

  • **kargs (keyword arguments) – Any other keyword arguments accepted by subprocess.Popen. See the Python documentation for subprocess.Popen for full info.

Returns:

DoneProcess | subprocess.Popen – If wait is True (default), returns a DoneProcess collecting all relevant info about the finished subprocess. See DoneProcess for details.

If wait is False, returns the created subprocess.Popen. In this case the user if fully responsible for handling the communication with the process, its termination, and the processing of its outcome.

Examples

>>> P = run("pwd")
>>> P.stdout.strip('\n') == os.getcwd()
True
>>> P = run("pwd", stdout=subprocess.PIPE)
>>> P.stdout.strip('\n') == os.getcwd()
True
>>> P = run("echo 'This is stderr' > /dev/stderr", shell=True)
>>> P.stderr
'This is stderr\n'
>>> P = run('false')
>>> P
DoneProcess(args=['false'], returncode=1, stdout='', stderr='')
>>> P = run('false', capture_output=False)
>>> P
DoneProcess(args=['false'], returncode=1)
>>> P.stdout is None
True
>>> P = run('False')
>>> P
DoneProcess(args=['False'], returncode=127, failed=True)
>>> P = run("sleep 5", timeout=1, capture_output=False)
>>> P
DoneProcess(args=['sleep', '5'], returncode=-1, timedout=True)
>>> print(P)
DoneProcess report
args: ['sleep', '5']
returncode: -1
timedout: True
>>> P = run("sleep 10", wait=False)
>>> P.poll() is None
True