Run An External Command From A Python Script
import subprocess
echo_cmd = subprocess.run(
['echo', 'Hello world'],
capture_output=True,
)
if echo_cmd.returncode == 0:
print(echo_cmd.stdout.decode('utf-8').strip())
else:
print("there was an error")
Hello world
NOTE:
If the return code isn't `0` You might be able to get the error from
print(echo_cmd.stderr.decode('utf-8').strip())
NOTE:
If you use
check=True
It'll throw a crashing error if the process fails
For those times when you need to execute another process
import subprocess
response = subprocess.run(['ls', '-la'], stdout=subprocess.PIPE).stdout.decode('utf-8')
It pulls the output from STDOUT into the variable.
There's another way to do this where you don't do the pipe and then pull the values from inside the response variable that is what you should probably move to since it gives you stderr as well
Note from the docs` function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.
NOTE: subprocess.run does not work out of the box with pyfakefs
post- write these up with examples of all the different ways to get stuff with STDERR and STDOUT
via: https://stackoverflow.com/questions/89228/how-to-call-an-external-command
2020: Most Basic for after Python 3.5
#!/usr/bin/env python3
# This runs, but doesn't send results back to python,
import subprocess
subprocess.run(["ls", "-l"])
# If you do this:
print(subprocess.run(["ls", "-l"]))
# You get something like:
# -rw-r--r-- 1 alans staff 187 Oct 20 20:46 test_credentials.py
# CompletedProcess(args=['ls', '-l'], returncode=0)
# But the line with the list stuff is directly from the
# STDOUT that subprocess did. It's not what was passed
# back to print.
#Prior to Python 3.5
#!/usr/bin/env python2
import subprocess
subprocess.call(["ls", "-l"])
TODO determine differ with stdout here
subprocess.run().stdout.decode('utf-8')
Get just stdout with, see this below
--------------------------------------------------------------------------------
# This one is how you run commands that are already assembled
import os
os.system("some_command < input_file | another_command > output_file")
--------------------------------------------------------------------------------
To pull the STDOUT directly (without access to STDERR) in a way that will just capture STDOUT , use
# This is for python3
import subprocess
response = subprocess.run(['ls', '-la'], stdout=subprocess.PIPE).stdout.decode('utf-8')
> You can capture errors by passing stderr=subprocess.PIPE (capture to result.stderr) or stderr=subprocess.STDOUT (capture to result.stdout along with regular output). When security is not a concern, you can also run more complex shell commands by passing shell=True as described in the notes below.
via: <<link|this StackOverflow Answer|https://stackoverflow.com/a/4760517/102401>>:
--------------------------------------------------------------------------------
From [this StackOverflow Answer] (https://stackoverflow.com/a/89243/102401):
> The advantage of subprocess vs. system is that it is more flexible (you can get the stdout, stderr, the "real" status code, better error handling, etc...).
>
> The <<link|official documentation|https://docs.python.org/3/library/os.html#os.system) recommends the subprocess module over the alternative os.system(>>
subprocess.check_output()
-------------------------
via: https://stackoverflow.com/a/4760517/102401
If you just need the output, use `subprocess.check_output`, like:
response = subprocess.check_output(['awslocal', 'logs', 'describe-log-groups']).decode('utf-8')
The principal output is a binary object which is why the `.decode('utf-8')` is there
Apparently, this isn't the recommended approach, but it still works.
--------------------------------------------------------------------------------
This is how you can get output from an external command in python.
import subprocess
print subprocess.Popen("echo Hello World", stdout=subprocess.PIPE, shell=True).stdout.read()
Note that if you want to catch errors as well (for example to deal with git) it looks like you need to do something like:
git_status_response = subprocess.Popen("git status", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True).stdout.read()
If you want to remove the newline from the end, you can add '.rstrip()'. for example:
git_status_response = subprocess.Popen("git status", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True).stdout.read().rstrip()
That one is not tested yet, but another version like it worked.
Note, it looks like 'subprocess.check_output' doesn't always work. You had problems using it inside of Sublime Text.
--------------------------------------------------------------------------------
---
Older Notes
This is from this [stack overflow question][1]
def gitAdd(fileName, repoDir):
cmd = ['git', 'add', fileName]
p = subprocess.Popen(cmd, cwd=repoDir)
p.wait()
gitAdd('exampleFile.txt', '/usr/local/example_git_repo_dir')
[1]: http://stackoverflow.com/questions/1456269/python-git-module-experiences