[Python-ideas] shutil.run (Was: shutil.runret and shutil.runout)
anatoly techtonik
techtonik at gmail.com
Tue May 22 17:39:16 CEST 2012
Hello again,
I've finally found some time to partially process the replies and
came up with a better solution than subprocess.* and
shutil.runret/runout
Disclaimer: I don't say that suprocess suxx - it is powerful and very
awesome under the hood. What I want to say that its final user
interface is awful - for such complex thing as this it should have
been passed through several iteration cycles before settling down.
Therefore, inspired by Fabric API, I've finally found the solution -
shutil.run() function:
https://bitbucket.org/techtonik/shutil-run/src
run(command, combine_stderr=True):
Run command through a system shell, return output string with
additional properties:
output.succeeded - result of the operation True/False
output.return_code - specific return code
output.stderr - stderr contents if combine_stderr=False
`combine_stderr` if set, makes stderr merged into output string,
otherwise it will be available as `output.stderr` attribute.
Example:
from shellrun import run
output = run('ls -la')
if output.succeeded:
print(output)
else:
print("Error %s" % output.return_code)
That's the most intuitive way I found so far. Objective advantages:
1. Better than
subprocess.call(cmd, shell=true)
subprocess.check_call(cmd, shell=true)
subprocess.check_output(cmd, shell=True)
because it is just
shutil.run(cmd)
i.e. short, simple and _easy to remember_
2. With shutil.run() you don't need to rewrite your check_call() or
check_output() with Popen() if you need to get return_code in addition
to stderr contents on error
3. shutil.run() is predictable and consistent - its arguments are not
dependent on each other, their combination doesn't change the function
behavior over and over requiring you iterate over the documentation
and warnings again and again
4. shutil.run() is the correct next level API over subprocess base
level. subprocess executes external process - that is its role, but
automatic ability to execute external process inside another external
process (shell) looks like a hack to me. Practical, but still a hack.
5. No required exception catching, which doesn't work for shell=True anyway
6. No need to learn subprocess.PIPE routing magic (not an argument for
hackers, I know)
Subjective advantages:
1. More beautiful
2. More simple
3. More readable
4. Practical
5. Obvious
6. It easy to explain
Hopefully, it can find its way in stdlib instead of
http://shell-command.readthedocs.org/
--
anatoly t.
More information about the Python-ideas
mailing list