title: Suppress stdout / stderr print from Python functions
body: <p>I have a Python script that is using some closed-box Python functions (i.e. I can't edit these functions) provided by my employer. When I call these functions, they are printing output to my linux terminal that I would like to suppress. I've tried redirecting stdout / stderr via;</p>
  
  <pre><code>orig_out = sys.stdout
  sys.stdout = StringIO()
  rogue_function()
  sys.stdout = orig_out
  </code></pre>
  
  <p>but this fails to catch the output. I think the functions I'm calling via-Python (rogue_function() from above) are really wrappers for compiled C-code, which are actually doing the printing. </p>
  
  <p>Does anyone know of a way I can do a "deep-capture" of any print handed to stdout / stderr by a function (and any sub-functions that function calls)? </p>
  
  <p><strong>UPDATE</strong>:</p>
  
  <p>I ended up taking the method outlined in the selected answer below and writing a context manager to supress stdout and stderr:</p>
  
  <pre><code># Define a context manager to suppress stdout and stderr.
  class suppress_stdout_stderr(object):
      '''
      A context manager for doing a "deep suppression" of stdout and stderr in 
      Python, i.e. will suppress all print, even if the print originates in a 
      compiled C/Fortran sub-function.
         This will not suppress raised exceptions, since exceptions are printed
      to stderr just before a script exits, and after the context manager has
      exited (at least, I think that is why it lets exceptions through).      
  
      '''
      def __init__(self):
          # Open a pair of null files
          self.null_fds =  [os.open(os.devnull,os.O_RDWR) for x in range(2)]
          # Save the actual stdout (1) and stderr (2) file descriptors.
          self.save_fds = [os.dup(1), os.dup(2)]
  
      def __enter__(self):
          # Assign the null pointers to stdout and stderr.
          os.dup2(self.null_fds[0],1)
          os.dup2(self.null_fds[1],2)
  
      def __exit__(self, *_):
          # Re-assign the real stdout/stderr back to (1) and (2)
          os.dup2(self.save_fds[0],1)
          os.dup2(self.save_fds[1],2)
          # Close all file descriptors
          for fd in self.null_fds + self.save_fds:
              os.close(fd)
  </code></pre>
  
  <p>To use this you just:</p>
  
  <pre><code>with suppress_stdout_stderr():
      rogue_function()
  </code></pre>
  
  <p>This works "pretty good". It does suppress the printout from the rogue functions that were cluttering up my script. I noticed in testing it that it lets through raised exceptions as well as some logger print, and I'm not entirely clear why. I think it has something to do with <em>when</em> these messages get sent to stdout / stderr (I think it happens after my context manager exits). If anyone can confirm this, I'd be interested in hearing the details ... </p>