Suppress output in Python calls to executables

Question:

I have a binary named A that generates output when called. If I call it from a Bash shell, most of the output is suppressed by A > /dev/null. All of the output is suppressed by A &> /dev/null

I have a python script named B that needs to call A. I want to be able to generate output from B, while suppressing all the output from A.

From within B, I’ve tried os.system('A'), os.system('A > /dev/null'), and os.system('A &> /dev/null'), os.execvp('...'), etc. but none of those suppress all the output from A.

I could run B &> /dev/null, but that suppresses all of B‘s output too and I don’t want that.

Anyone have suggestions?

Asked By: Lin

||

Answers:

As the os.system() docs mention, use the subprocess module, and, if you like, set stdout=open(os.devnull, ‘w’) (and perhaps the same for stderr) when you open the subprocess.

Answered By: Devin Jeanpierre

If you have Python 2.4, you can use the subprocess module:

>>> import subprocess
>>> s = subprocess.Popen(['cowsay', 'hello'], 
      stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
>>> print s
 _______ 
< hello >
 ------- 
           ^__^
           (oo)_______
            (__)       )/
                ||----w |
                ||     ||
Answered By: Manuel
import os
import subprocess

command = ["executable", "argument_1", "argument_2"]

with open(os.devnull, "w") as fnull:
    result = subprocess.call(command, stdout = fnull, stderr = fnull)

If the command doesn’t have any arguments, you can just provide it as a simple string.

If your command relies on shell features like wildcards, pipes, or environment variables, you’ll need to provide the whole command as a string, and also specify shell = True. This should be avoided, though, since it represents a security hazard if the contents of the string aren’t carefully validated.

Answered By: DNS

I know it’s late to the game, but why not simply redirect output to /dev/null from within os.system? E.g.:

tgt_file = "./bogus.txt"
os.sytem("d2u '%s' &> /dev/null" % tgt_file)

This seems to work for those occasions when you don’t want to deal with subprocess.STDOUT.

Answered By: Rob Carr

If your search engine lead you to this old question (like me), be aware that using PIPE may lead to deadlocks.
Indeed, because pipes are buffered, you can write a certain number of bytes in a pipe, even if no one read it. However the size of buffer is finite. And consequently if your program A has an output larger than the buffer, A will be blocked on writing, while the calling program B awaits the termination of A. But not, in this particular case… see comments below.

Still, I recommend using Devin Jeanpierre and DNS’ solution.

Answered By: Po' Lazarus

I use:

call(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

where command is the string of the command + arguments

For this to work you must import subprocess

Answered By: TTT

If you need to just capture STDOUT, doesn’t assigning it to a variable do this? For example:

megabyte=''
# Create a 1 MiB string of NULL characters.
for i in range(1048576):
    megabyte += ''
fh=open('zero.bin','w')
# Write an 8 GiB file.
for i in range(8192):
    print(i)
    # Suppress output of 'write()' by assigning to a variable.
    discard=fh.write(megabyte)
fh.close()

I was creating a large zero-filled file to zero free space on my hard drive and discovered that each call to handle.write(string) spit out the number of bytes written. Assigning it to a vairable suppressed that output.

Answered By: ECJB

In Python 3.3 and higher, subprocess supports an option for redirecting to /dev/null. To use it, when calling .Popen and friends, specify stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, as keyword arguments.

So DNS’s answer, rewritten for Python 3.3+, becomes

import subprocess
command = ["executable", "argument_1", "argument_2"]
result = subprocess.call(command,
                         stdout=subprocess.DEVNULL,
                         stderr=subprocess.DEVNULL)

From the documentation:

subprocess.DEVNULL¶

Special value that can be used as the stdin, stdout or stderr
argument to Popen and indicates that the special file os.devnull will
be used.

New in version 3.3.

For Python 3.0 to 3.2, you have to manually open the null device using open(os.devnull), as DNS wrote.

Answered By: Mechanical snail

If you do not want to wait for the command to complete, such as starting a backup task, another option is to pass it through bash, doing which allows the redirect to operate normally.

For example, starting a sound file using aplay:

import os

def PlaySound(filename):
    command = 'bash -c "aplay %s &> /dev/null &"' % (filename)
    os.system(command)

This way I can spawn a new process, not wait for it to finish and stop it from printing to the terminal.
The only catch is that it will load a bash instance as well as the process you are running, providing a slight overhead.

Answered By: PiBorg
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.