ubelt.util_cmd module

ubelt.util_cmd.cmd(command, shell=False, detatch=False, verbose=0, verbout=None, tee='auto')[source]

Executes a command in a subprocess.

The advantage of this wrapper around subprocess is that (1) you control if the subprocess prints to stdout, (2) the text written to stdout and stderr is returned for parsing, (3) cross platform behavior that lets you specify the command as a string or tuple regardless of whether or not shell=True. (4) ability to detatch, return the process object and allow the process to run in the background (eventually we may return a Future object instead).

Parameters:
  • command (str) – bash-like command string or tuple of executable and args
  • shell (bool) – if True, process is run in shell
  • detatch (bool) – if True, process is detached and run in background.
  • verbose (int) – verbosity mode. Can be 0, 1, 2, or 3.
  • verbout (int) – if True, command writes to stdout in realtime. defaults to True iff verbose > 0. Note when detatch is True all stdout is lost.
  • tee (str) – backend for tee output. Can be either: auto, select (POSIX only), or thread.
Returns:

info - information about command status.

if detatch is False info contains captured standard out, standard error, and the return code if detatch is False info contains a reference to the process.

Return type:

dict

Notes

Inputs can either be text or tuple based. On unix we ensure conversion to text if shell=True, and to tuple if shell=False. On windows, the input is always text based. See [3] for a potential cross-platform shlex solution for windows.

CommandLine:
python -m ubelt.util_cmd cmd python -c “import ubelt as ub; ub.cmd(‘ping localhost -c 2’, verbose=2)”

References

[1] https://stackoverflow.com/questions/11495783/redirect-subprocess-stderr-to-stdout [2] https://stackoverflow.com/questions/7729336/how-can-i-print-and-display-subprocess-stdout-and-stderr-output-without-distorti [3] https://stackoverflow.com/questions/33560364/python-windows-parsing-command-lines-with-shlex

Example

>>> info = cmd(('echo', 'simple cmdline interface'), verbose=1)
simple cmdline interface
>>> assert info['ret'] == 0
>>> assert info['out'].strip() == 'simple cmdline interface'
>>> assert info['err'].strip() == ''
Doctest:
>>> info = cmd('echo str noshell', verbose=0)
>>> assert info['out'].strip() == 'str noshell'
Doctest:
>>> # windows echo will output extra single quotes
>>> info = cmd(('echo', 'tuple noshell'), verbose=0)
>>> assert info['out'].strip().strip("'") == 'tuple noshell'
Doctest:
>>> # Note this command is formatted to work on win32 and unix
>>> info = cmd('echo str&&echo shell', verbose=0, shell=True)
>>> assert info['out'].strip() == 'str\nshell'
Doctest:
>>> info = cmd(('echo', 'tuple shell'), verbose=0, shell=True)
>>> assert info['out'].strip().strip("'") == 'tuple shell'
Doctest:
>>> import ubelt as ub
>>> from os.path import join, exists
>>> fpath1 = join(ub.get_app_cache_dir('ubelt'), 'cmdout1.txt')
>>> fpath2 = join(ub.get_app_cache_dir('ubelt'), 'cmdout2.txt')
>>> ub.delete(fpath1)
>>> ub.delete(fpath2)
>>> info1 = ub.cmd(('touch', fpath1), detatch=True)
>>> info2 = ub.cmd('echo writing2 > ' + fpath2, shell=True, detatch=True)
>>> while not exists(fpath1):
...     pass
>>> while not exists(fpath2):
...     pass
>>> assert ub.readfrom(fpath1) == ''
>>> assert ub.readfrom(fpath2).strip() == 'writing2'
>>> info1['proc'].wait()
>>> info2['proc'].wait()