Question: I want to hide stdout/stderr in a python script **BUT** the print is not done into the python script itself but inside the underlying .c extension when a python module needs one.

it is the case for *netsnmp* python module, it requires compilation, the problem is that there are some 'printf' directly into the C (client\_intf.c) code that I would like to capture and hide :

```
from netsnmp import *
import sys,os
devnull = open(os.devnull, 'w')
sys.stdout, sys.stderr = devnull, devnull
session = Session(DestHost='myhostthatdoesnotexisttogenerateerror',Version=2,Community='demopublic')

```

When I run it I still have some traces :

```
python test.py
getaddrinfo: myhostthatdoesnotexisttogenerateerror nodename nor servname provided, or not known
error:snmp_new_session: Couldn't open SNMP session

```

How can I get rid of these messages on stdout/stderr ? this is important because I am developping Nagios plugins, and I can afford such output (nevertheless, I want to capture them to raise a custom exception)

Answer: 
Eric's answer is excellent but it has an important drawback: if you already used `sys.stderr` to initialize some stuff it will become useless. As an example: if you created a custom error logger using `sys.stderr` it will stop working.

Here is a modified version:

```py
import os
from contextlib import contextmanager

@contextmanager
def hide_stderr():
    """ Low level stderr supression. """
    newstderr = os.dup(2)
    devnull = os.open('/dev/null', os.O_WRONLY)
    os.dup2(devnull, 2)
    os.close(devnull)
    yield
    os.dup2(newstderr, 2)

@contextmanager
def hide_stdout():
    """ Low level stdout supression. """
    newstderr = os.dup(1)
    devnull = os.open('/dev/null', os.O_WRONLY)
    os.dup2(devnull, 1)
    os.close(devnull)
    yield
    os.dup2(newstderr, 1)

import sys

my_stderr = sys.stderr
print("Test 1: no stderr, no stdout")
with hide_stderr():
    with hide_stdout():
        print("1 stdout")
        print("2 stderr", file=my_stderr)
print("Test 2: no stderr, but stdout")
with hide_stderr():
    print("1 stdout")
    print("2 stderr", file=my_stderr)
print("Test 3: stderr, no stdout")
with hide_stdout():
    print("1 stdout")
    print("2 stderr", file=my_stderr)
print("Test 4: stderr and stdout")
print("1 stdout")
print("2 stderr", file=my_stderr)

```

Note that the main difference is the use of `os.dup2` at the end. We recover the file descriptor from the copy we did and we don't mess with `sys.stderr`.
Depending on your OS (seems to work on both Windows and Linux at least) the following would shut up fx `stdout` completely, by replacing the (low level) file descriptor:

```
nulf = os.open(os.devnull, os.O_WRONLY)
os.dup2(nulf, stdout.fileno())
os.close(nulf)

```

the same to `stderr` doesn't seem to work that well in interactive mode (I guess that the python interpreter tries to write it's stuff to stderr).

This solution will have the same effect that redirect to `/dev/null` or equivalent when starting the interpreter (except it takes effect later), including any printouts that are made in native code (and of course any printout your script is trying to do). If you want to do any logging you would have to open a file for that (you could also open a file other than `os.devnull` in the first place if you'd like to redirect `stdout` to a file instead).

Note that normally a program doesn't check the result of printouts and in that case one could simply close the descriptor (ie `os.close(stdout.fileno())`), but that would fail if the extension actually checks the results and acts differently based on that.