78

I want to get the output from some shell commands like ls or df in a python script. I see that commands.getoutput('ls') is deprecated but subprocess.call('ls') will only get me the return code.

I'll hope there is some simple solution.

rypel
  • 4,686
  • 2
  • 25
  • 36
Rafael T
  • 15,401
  • 15
  • 83
  • 144

3 Answers3

116

Use subprocess.Popen:

import subprocess
process = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
print(out)

Note that communicate blocks until the process terminates. You could use process.stdout.readline() if you need the output before it terminates. For more information see the documentation.

Balaji Dubey
  • 446
  • 5
  • 10
Michael Smith
  • 1,847
  • 2
  • 19
  • 19
  • The correct current doc link for the Python 2.7 version of `subprocess` examples is: http://docs.python.org/library/subprocess.html#replacing-older-functions-with-the-subprocess-module ; for Python 3.2, http://docs.python.org/py3k/library/subprocess.html#replacing-older-functions-with-the-subprocess-module – Ned Deily Jul 11 '11 at 23:09
  • 5
    You probably need to replace the subprocess.communicate() with process.communicate() - you may also need the subprocess exit code by doing process.returncode – Cinquo Jul 11 '11 at 23:11
  • I didn't notice that I had written subprocess instead of process. Fixed. – Michael Smith Jul 11 '11 at 23:13
  • what types are out and err? are they regular strings or are they arrays or dictionaries? – scottysseus Aug 06 '13 at 18:02
  • 3
    Works fine for `out` but `err` will be uninitialized and the error output printed to the screen. You'll have to specify `stderr=subprocess.PIPE` in addition to `stdout` to get the standard error. – Gerrit-K Aug 20 '14 at 19:09
  • What type is "out"? It looks like it's an object of some type because I cannot write it to a file like it's a string `subprocess.Popen(["echo", out, ">>", "/home/ec2-user/output_test.sh"], stdout=subprocess.PIPE)` – Kyle Bridenstine Jan 09 '19 at 21:43
56

For Python >= 2.7, use subprocess.check_output().

http://docs.python.org/2/library/subprocess.html#subprocess.check_output

knite
  • 6,033
  • 6
  • 38
  • 54
  • 8
    Technically, it should be `subprocess.check_output(cmd, shell=True)`. – Cerin Apr 18 '16 at 17:23
  • 1
    What is the difference shell True or False? – Ricky Wilson Jul 31 '17 at 16:11
  • 3
    I think it enables "shell specific features" like file globbing, piping etc... – Rafael T Sep 20 '17 at 13:41
  • 1
    @RickyWilson commands baked into the shell like 'dir' (or 'ls') will give you an error and not be found unless you pass in shell=True, along with the other shell-specific features like piping as stated above. Otherwise the subprocess cmd list should be a valid filepath and its arguments. Also when shell=True you may incur a max string length of the command allowed, depending on platform, whereas shell=False would allow a longer command to be digested than a shell would normally allow to be typed in manually. – Jordan Stefanelli Oct 14 '18 at 09:39
11

To catch errors with subprocess.check_output(), you can use CalledProcessError. If you want to use the output as string, decode it from the bytecode.

# \return String of the output, stripped from whitespace at right side; or None on failure.
def runls():
    import subprocess
    try:
        byteOutput = subprocess.check_output(['ls', '-a'], timeout=2)
        return byteOutput.decode('UTF-8').rstrip()
    except subprocess.CalledProcessError as e:
        print("Error in ls -a:\n", e.output)
        return None
Roi Danton
  • 7,933
  • 6
  • 68
  • 80