Hiding console output produced by os.system

Question:

I am calling this piece of code, but it produces some output in the console where I ran the python script (due to tee command):

os.system("echo 3 | sudo tee /proc/sys/vm/drop_caches")

This version does not produce console output but is there another way?

os.system('sudo bash -c "echo 3 > /proc/sys/vm/drop_caches"')
Asked By: ArekBulski

||

Answers:

Write directly to the proc pseudo file instead via Python i/o lib.

This will require your script to run as root (via sudo), which means you should limit its scope to being an admin only tool. This also allows the script to run on boxes where sudo requires a password.

Example:

with open("/proc/sys/vm/drop_caches", "w") as drop_caches:
    drop_caches.write("3")
Answered By: Alastair McCormack

To answer the question based on its title in the most generic form:

To suppress all output from os.system(), append >/dev/null 2>&1 to the shell command, which silences both stdout and stderr; e.g.:

import os
os.system('echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null 2>&1')

Note that os.system() by design passes output from the calling process’ stdout and stderr streams through to the console (terminal) – your Python code never sees them.

Also, os.system() does not raise an exception if the shell command fails and instead returns an exit code; note that it takes additional work to extract the shell command’s true exit code: you need to extract the high byte from the 16-bit value returned, by applying >> 8 (although you can rely on a return value other than 0 implying an error condition).


Given the above limitations of os.system(), it is generally worthwhile to use the functions in the subprocess module instead:

For instance, subprocess.check_output() could be used as follows:

import subprocess
subprocess.check_output('echo 3 | sudo tee /proc/sys/vm/drop_caches', shell=True) 

The above will:

  • capture stdout output and return it (with the return value being ignored in the example above)
  • pass stderr output through; passing stderr=subprocess.STDOUT as an additional argument would also capture stderr.
  • raise an error, if the shell command fails.

Note: Python 3.5 introduced subprocess.run(), a more flexible successor to both os.system() and subprocess.check_output() – see https://docs.python.org/3.5/library/subprocess.html#using-the-subprocess-module


Note:

  • The reason that the OP is employing tee in the first place – despite not being interested in stdout output – is that a naïve attempt to use > ... instead would be interpreted before sudo is invoked, and thus fail, because the required privileges to write to /proc/sys/... haven’t been granted yet.
  • Whether you’re using os.system() or a subprocess function, stdin is not affected by default, so if you’re invoking your script from a terminal, you’ll get an interactive password prompt when the sudo command is encountered (unless the credentials have been cached).
Answered By: mklement0

You also can use this simple method of subprocess module.

command = 'echo 3 | sudo tee /proc/sys/vm/drop_caches'
subprocess.check_call(shlex.split(command),stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL)

All outputs will be passed to DEVNULL. Any issues with the command will be reported by an exception. No issues means no output.

Answered By: Shtefan
subprocess.check_call(command,stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

you forgot to add stderr.

Answered By: Meltrix

I believe, the easiest way to hide the console output when it’s not possible with os.system is using os.popen:

os.popen("echo 3 | sudo tee /proc/sys/vm/drop_caches")
Answered By: maciejwww
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.