Welcome to Pysh’s documentation!¶
Preparing command lines¶
-
pysh.
shwords
(format_string, *args, **kwargs)¶ Split format_string, then format using args and kwargs, producing a list.
Handy for producing the command line for invoking an external program, conveniently but without the complex gotchas of shell parsing. For example:
>>> shwords('rm -rf /tmp/{userdoc}', userdoc='1 .. 2') ['rm', '-rf', '/tmp/1 .. 2']
The format_string is split on spaces. Each word is then formatted through a minilanguage similar to
str.format()
. Each word of format_string produces exactly one item in the result (unless explicitly instructed otherwise with{!@}
), regardless of the contents of the interpolated values.The formatting minilanguage is exactly the same as for
str.format()
, except:An additional conversion
!@
, as in{!@}
. This must appear in format_string as a whole word. The argument must be an iterable, and each element of the iterable becomes an element in the result.The conversions
!r
and!a
are omitted, because they only make sense within a Python context.No nested interpolation, as in
{:{}}
.
Running commands¶
These provide thin wrappers around subprocess
, mainly adding shwords()
.
The basic check_cmd()
is a small convenience helper, just composing
shwords()
with subprocess.check_call()
.
Similarly, check_cmd_f()
behaves like shwords_f()
composed with
subprocess.check_call()
: it processes the command format-string
much like an f-string.
The try_cmd()
variant provides more appropriate semantics when the
command’s failure is an expected condition, by returning a bool
for
success/failure rather than raising an exception on failure.
Similarly try_cmd_f()
.
The slurp_cmd()
function and the rest of its family run a command
for its output, with subprocess.check_output()
, and strip
trailing newlines. This matches the behavior of $(...)
in Bash
and fits nicely with conventional semantics for Unix CLI tools.
The behavior of slurp_cmd_f()
, try_slurp_cmd()
, and
try_slurp_cmd_f()
relate to slurp_cmd()
in the same way as
check_cmd_f()
, try_cmd()
, and try_cmd_f()
do to
check_cmd()
.
In short, these functions fill the following table:
check_cmd try_cmd
check_cmd_f try_cmd_f
slurp_cmd try_slurp_cmd
slurp_cmd_f try_slurp_cmd_f
-
pysh.
DEVNULL
¶ Has the same meaning for stdout/stderr arguments of these functions, and of
cmd.run
, as forsubprocess.Popen
.
-
pysh.
STDOUT
¶ Has the same meaning for stderr arguments of these functions, and of
cmd.run
, as forsubprocess.Popen
.
-
pysh.
check_cmd
(fmt, *args, _stdin=None, _stdout=None, _stderr=None, _cwd=None, _timeout=None, **kwargs) → None¶ Just like
subprocess.check_call()
, but withshwords()
.The named keyword arguments are passed through, with
stdin=_stdin
etc. All other arguments are passed toshwords()
.
-
pysh.
check_cmd_f
(fmt, **kwargs) → None¶ Just like
check_cmd()
, but withshwords_f()
instead ofshwords()
.This means fmt is processed much like an f-string, with access to the caller’s locals. See
shwords_f()
for details.Also, unlike
check_cmd()
all keyword arguments are passed straight through tosubprocess.check_call()
.
-
pysh.
try_cmd
(fmt, *args, **kwargs) → bool¶ Just like
check_cmd()
, but returns success/failure rather than raise.
-
pysh.
try_cmd_f
(fmt, **kwargs) → bool¶ Just like
check_cmd_f()
, but returns success/failure rather than raise.
-
pysh.
slurp_cmd
(fmt, *args, _stdin=None, _stderr=None, _cwd=None, _timeout=None, **kwargs) → str¶ Run the command and capture output, stripping any trailing newlines.
Stripping trailing newlines is the same behavior as
$(...)
has in Bash. It fits nicely with conventional semantics for Unix CLI tools.See also
pysh.slurp()
.
-
pysh.
slurp_cmd_f
(fmt, **kwargs) → str¶ Just like
slurp_cmd()
, but withshwords_f()
instead ofshwords()
.Also, like
check_cmd_f()
in contrast tocheck_cmd()
, all keyword arguments are passed straight through tosubprocess.check_output()
.
-
pysh.
try_slurp_cmd
(fmt, *args, **kwargs) → Optional[str]¶ Just like
slurp_cmd()
, but on failure returnsNone
rather than raise.
-
pysh.
try_slurp_cmd_f
(fmt, **kwargs) → Optional[str]¶ Just like
slurp_cmd_f()
, but on failure returnsNone
rather than raise.
Running pipelines¶
-
pysh.
slurp
(filter)¶ Run the pipeline and capture output, stripping any trailing newlines.
Stripping trailing newlines is the same behavior as
$(...)
has in Bash. It fits nicely with conventional semantics for Unix CLI tools.See also
pysh.slurp_cmd
.
-
pysh.
to_stdout
(filter)¶ Run the pipeline, with output directed to our stdout.
Commands in pipelines¶
-
pysh.cmd.
run
(fmt, *args, _check=True, _stderr=None)¶ Run the given external command, as a pipeline filter.
Like any filter, the return value of
cmd.run()
only has an effect when a pipeline containing it is run by a function likeslurp()
orto_stdout()
. When run:The given fmt and *args are interpreted by
shwords()
to produce a command line.The command line is executed (using
subprocess.Popen
), with stdin and stdout connected to the filter’s input and output in the pipeline. Input is optional.The external command’s stderr can be controlled with _stderr, using values
None
,pysh.DEVNULL
, orpysh.STDOUT
.If _check is true (the default), an exception is raised on failure just like
check_cmd()
. Otherwise, the external command’s return code is ignored.
NOTE: In the current implementation, the input may be read completely into a buffer before any of it is passed to the external command. This is just fine for lots of scripts, but will be fixed before Pysh 1.0. If you have a use case where this matters, please file an issue, to help prioritize fixing it.
-
pysh.cmd.
splitlines
()¶ Split the input stream into an iterator of lines.
The meaning of “line” follows the standard Unix convention:
Each newline byte (
b'\n'
) terminates a line.If there are any bytes after the last newline, they form one last line.
This is also the same behavior as Python’s
bytes.splitlines()
, except that onlyb'\n'
counts as a newline:b'\r'
is treated the same as any other byte.
-
pysh.cmd.
cat
(*filenames)¶ Read each of the given files in turn, and output their contents.
This is very similar to the Unix command
cat
, but with fewer features:The filenames are never interpreted as options; they’re simply filenames.
The filename
-
, or an empty list of filenames, are not special; instead of reading from stdin, they cause reading from a file named-
, and an empty output, respectively.
-
pysh.cmd.
echo
(*words, ln=True)¶ Write the given words to the output.
The words are separated by blanks
b' '
. If ln is true (the default), a newlineb'\n'
follows at the end.This corresponds to the Unix command
echo
, withln=False
corresponding toecho -n
.For example:
>>> pysh.to_stdout( cmd.echo(b'hello', b'world') ) hello world
-
pysh.cmd.
devnull
()¶ Ignore any input, and provide nothing as output.
This corresponds to a shell redirection from or to
/dev/null
. In particular:a shell command like
… </dev/null
corresponds to a Pysh pipelinecmd.devnull() | …
;a shell command like
… >/dev/null
corresponds to a Pysh pipeline… | cmd.devnull()
.