Using subprocess.check_output for a command with 2>/dev/null

10.5k Views Asked by At

I am on Mac OS X Yosemite 10.10 and Python 2.7.

If I type the following: du -g -d1 /Users 2> /dev/null in the command line, everything works perfectly.

Now, my goal is to use that command in a python script.

My idea was to use the following:

import subprocess

output = subprocess.check_output(['du', '-g', '-d1', '/Users', '/dev/null'])

But I get this error:

Traceback (most recent call last):
  File "./verifications.py", line 1, in <module>
    output = subprocess.check_output(['du', '-g', '-d1', '/Users', '/dev/null'])
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 537, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['du', '-g', '-d1', '/Users', '/dev/null']' returned non-zero exit status 1

Also, when I run subprocess.check_output(['du', '-g', '-d1', '/Users', '/dev/null']) in local everything works fine, the error happens when I am logged on a shared iMac using Apple's Shared Screen tool. I have a feeling that the problem might be due to permissions, but I cannot find anything.

1

There are 1 best solutions below

20
On BEST ANSWER

For 2>/dev/null, the appropriate way to control redirection of file descriptor 2 with the subprocess.Popen family of calls is stderr=:

# Python 2.x, or 3.0-3.2
output = subprocess.check_output(['du', '-g', '-d1', '/Users'],
                                 stderr=open('/dev/null', 'w'))

...or, with a Python supporting subprocess.DEVNULL:

# Python 3.3 or newer
output = subprocess.check_output(['du', '-g', '-d1', '/Users'],
                                  stderr=subprocess.DEVNULL)

By the way, personally, I'd suggest something more like this:

p = subprocess.Popen(['du', '-g', '-d1', '/Users'],
                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
  raise Exception(stderr)

...which, instead of sending stderr to /dev/null, keeps it around to use in generating a useful exception in the event that the command fails. (Pick an appropriate subclass of Exception, obviously).