382

I'm using eSpeak on Ubuntu and have a Python 2.7 script that prints and speaks a message:

import subprocess text = 'Hello World.' print text subprocess.call(['espeak', text]) 

eSpeak produces the desired sounds, but clutters the shell with some errors (ALSA lib..., no socket connect) so i cannot easily read what was printed earlier. Exit code is 0.

Unfortunately there is no documented option to turn off its verbosity, so I'm looking for a way to only visually silence it and keep the open shell clean for further interaction.

How can I do this?


See Python os.system without the output for approaches specific to os.system - although modern code should normally use the subprocess library instead.

6
  • could you not just call with os.system then? not ideal but shouldnt print i dont think Commented Jun 29, 2012 at 22:12
  • @JoranBeasley: os.system() will print to the console unless you redirect the shell command Commented Jun 29, 2012 at 22:16
  • no, os.system('espeak '+ text) reproduces this behavior. Commented Jun 29, 2012 at 22:17
  • @ferkulat: I updated my answer to also show the os.system syntax. Though it is just for illustration. Stick with subprocess Commented Jun 29, 2012 at 22:19
  • 2
    Non 2.7 specific version: stackoverflow.com/questions/5495078/… which allows for the perfect subprocess.DEVNUL solution. Commented Mar 21, 2015 at 8:26

5 Answers 5

614

For python >= 3.3, Redirect the output to DEVNULL:

import os import subprocess retcode = subprocess.call(['echo', 'foo'], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) 

For python <3.3, including 2.7 use:

FNULL = open(os.devnull, 'w') retcode = subprocess.call(['echo', 'foo'], stdout=FNULL, stderr=subprocess.STDOUT) 

It is effectively the same as running this shell command:

retcode = os.system("echo 'foo' &> /dev/null") 
Sign up to request clarification or add additional context in comments.

16 Comments

micro neat picks: you could use os.devnull if subprocess.DEVNULL is not available (<3.3), use check_call() instead of call() if you don't check its returned code, open files in binary mode for stdin/stdout/stderr, usage of os.system() should be discouraged, &> doesn't work for sh on Ubuntu an explicit >/dev/null 2>&1 could be used.
@J.F.Sebastian: Thanks for the suggestions. I actually meant to use os.devnull but accidentally typed it out. Also, I am sticking with the OPs use of call since they are not catching the possible exception check_call would raise. And for the os.system redirect, it was more just an illustration of what the effective use of the subprocess approach is doing. Not really as a second suggestion.
Don't you need to close the FNULL that you have opened?
Just a note, you can use close_fds=True in subprocess.call to close the FNULL descriptor after the subprocess exists
@ewino: On close_fds=True, file descriptors are closed after fork() but before execvp() i.e., they are closed in the child process just before the executable is run. close_fds=True won't work on Windows if any of the streams are redirected. close_fds does not close files in the parent process.
|
106

Here's a more portable version (just for fun, it is not necessary in your case):

#!/usr/bin/env python # -*- coding: utf-8 -*- from subprocess import Popen, PIPE, STDOUT try: from subprocess import DEVNULL # py3k except ImportError: import os DEVNULL = open(os.devnull, 'wb') text = u"René Descartes" p = Popen(['espeak', '-b', '1'], stdin=PIPE, stdout=DEVNULL, stderr=STDOUT) p.communicate(text.encode('utf-8')) assert p.returncode == 0 # use appropriate for your program error handling here 

4 Comments

Note that this produces a DEVNULL which isn't fully general, like the one provided by subprocess; since it's opened wb it can't be used for stdin.
@Reid: you could use 'r+b' mode if you need it instead.
@jfs 8 years later we just do stdout=subprocess.DEVNULL, right?
the code is Python 2/3 compatible. If you don't need Python 2, then the import: from subprocess import DEVNULL is enough.
37

Use subprocess.check_output (new in python 2.7). It will captures stdout as the return value of the function, which both prevents it from being sent to standard out and makes it availalbe for you to use programmatically. Like subprocess.check_call, this raises an exception if the command fails, which is generally what you want from a control-flow perspective. Example:

import subprocess try: output = subprocess.check_output(['espeak', text]) except subprocess.CalledProcessError: # Handle failed call 

You can also suppress stderr with:

 output = subprocess.check_output(["espeak", text], stderr=subprocess.STDOUT) 

For earlier than 2.7, use

import os import subprocess with open(os.devnull, 'w') as FNULL: try: output = subprocess._check_call(['espeak', text], stdout=FNULL) except subprocess.CalledProcessError: # Handle failed call 

Here, you can suppress stderr with

 output = subprocess._check_call(['espeak', text], stdout=FNULL, stderr=FNULL) 

3 Comments

More precisely, it returns the stdout. Which is great as might want to use it as well besides being able to ignore it.
I think this is more straightforward. @StudentT I think you should handle errors with CalledProcessError. except subprocess.CalledProcessError as e and then use e.code or e.output
this was useful for more complex shell commands using variables & communicating with a REST service (subprocess.run did not work in my case)
34

As of Python3 you no longer need to open devnull and can call subprocess.DEVNULL.

Your code would be updated as such:

import subprocess text = 'Hello World.' print(text) subprocess.call(['espeak', text], stderr=subprocess.DEVNULL) 

1 Comment

Works! In addition, can swap stderr with stdout in code above (or append as another argument) to suppress outputs. "Outputs" is in the title of the question and what lead me here...maybe trivial, but thought it was worth mentioning.
-7

Why not use commands.getoutput() instead?

import commands text = "Mario Balotelli" output = 'espeak "%s"' % text print text a = commands.getoutput(output) 

1 Comment

a) it doesn't discard input, it accumulates it in memory unnecessarily b) it breaks if text has quotes in it, or uses a different character encoding, or too large for a command line c) it is Unix only (on Python 2)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.