From a6582aa8f28b483515025d58ed0435131c586734 Mon Sep 17 00:00:00 2001 From: wirawan Date: Fri, 28 May 2010 18:45:51 +0000 Subject: [PATCH] * pipe_in() for "piping in" input to an external command. * system() like os.system() except with error checking. * getenv() to get look for a value from a list of environment variables-- they are searched sequentially in definite order. --- shell_tools.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/shell_tools.py b/shell_tools.py index 002f4f6..ed0f78d 100644 --- a/shell_tools.py +++ b/shell_tools.py @@ -1,4 +1,4 @@ -# $Id: shell_tools.py,v 1.6 2010-02-19 18:40:19 wirawan Exp $ +# $Id: shell_tools.py,v 1.7 2010-05-28 18:45:51 wirawan Exp $ # # wpylib.shell_tools # Created: 20100106 @@ -70,6 +70,21 @@ def env_pop(name, old_value): else: os.environ[name] = old_value +def getenv(*names, **opts): + """Tries to get a value from a list of environment variables. + The first found one will be used; if none is found, then a default will + be tried (use `default' parameter to specify this). + If no default is found, then a KeyError exception will be raised. + """ + for n in names: + if n in os.environ: + return os.environ[n] + if "default" in opts: + return opts["default"] + else: + raise KeyError, \ + "Cannot find value among environment variables: %s" % (str(names)) + # Low-level utilities: def errchk(cmd, args, retcode): @@ -101,6 +116,15 @@ def quote_cmdline(seq): rslt.append(inew) return " ".join(rslt) + +""" +pipe_out and pipe_in defines unidirectional pipes for external programs. +Note the unconventional meaning: `pipe_in' means we drive the program with +python input as the stdin, `pipe_out' means we run the program and read in +the output into python. +""" + + if has_subprocess: def run(prg, args): @@ -108,6 +132,13 @@ if has_subprocess: errchk(prg, args, retcode) return 0 + def system(cmdline): + """Similar to os.system(), except that errors are caught. + cmdline *must* be a string.""" + retcode = subprocess.call(cmdline, shell=True) + errchk(cmdline, (), retcode) + return 0 + def pipe_out(args, split=False, shell=False): """Executes a shell command, piping out the stdout to python for parsing. This is my customary shortcut for backtick operator. @@ -119,6 +150,21 @@ if has_subprocess: else: return retval.splitlines() + class pipe_in: + """Executes a shell command, piping in the stdin from python for driving. + This is the reverse of pipe_out. + Commands are given through file-like write() or writelines() methods.""" + def __init__(self, args, shell=False): + self.px = subprocess.Popen(args, stdin=subprocess.PIPE, shell=shell) + self.args = args + def write(self, line): + self.px.stdin.write(line) + def writelines(self, lines): + for line in lines: + self.write(line) + def close(self): + self.px.stdin.close() + else: def run(prg, args=()): @@ -127,6 +173,12 @@ else: errchk(prg, args, retcode) return 0 + def system(cmdline): + """Similar to os.system(), except that errors are caught.""" + retcode = os.system(cmdline) + errchk(cmdline, (), retcode) + return 0 + def pipe_out(args, split=False, shell=False): """Executes a shell command, piping out the stdout to python for parsing. This is my customary shortcut for backtick operator. @@ -145,6 +197,18 @@ else: else: return retval.splitlines() + def pipe_in(args, shell=False): + """Executes a shell command, piping in the stdin from python for driving. + This is the reverse of pipe_out. + Commands are given through file-like write() or writelines() methods.""" + if shell or isinstance(args, str): + # BEWARE: args should be a string in this case + p = os.popen(args, "w") + else: + args = quote_cmdline(args) + p = os.popen(args, "w") + return p + # coreutils