Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redirecting current runing python process' stdout

I have python code that runs C code that spams stdout and stderr.

I want to suppress that stdout and stderr, without being able to modify the C code. As pseudocode, roughly:

def external_api_I_cant_control():
    C code that outputs to stdout & stderr # this is not a subprocess 
                                           # call which I can redirect
                                           # its stdout & stderr. Rather,
                                           # it's a wrapper for it so there
                                           # is nothing I can do to control its
                                           # FD

def do_stuff():
    external_api_I_cant_control()

My code is being run using python bla.py and so, I can redirect stderr using python bla.py 2>/dev/null, however this does not fix my problem, as some of the spam is to stdout and I can't redirect stdout - because I need some of it.

Is it possible to do, from within my code, the equivalent of shell stdout redirection?

I tried so far:

  1. contextlib.redirect_stdout
  2. replacing sys.stdout and sys.__stdout__ with open(os.devnull, 'w')

My desired outcome would be the equivalent of splitting my bla.py into 3 and running it like this:

python bla0.output.is.legit.py
python bla1.output.should.be.disregarded.py &> /dev/null
python bla2.output.is.legit.again.py

What would be the way to achieve this?

like image 850
CIsForCookies Avatar asked Jan 21 '26 17:01

CIsForCookies


1 Answers

This is a job for os.dup2(). The code you want consists of three stages:

  • Backing up the original stdout and stderr
  • Replacing stdout and stderr with file handles pointing at /dev/null
  • Restoring the backups (after running the code you want).

# create a backup of stdout and stderr
orig_stdout_fd = os.dup(1)
orig_stderr_fd = os.dup(2)

# make the original stdout and stderr point to /dev/null
devnull = open('/dev/null', 'r+')
os.dup2(devnull.fileno(), 1)
os.dup2(devnull.fileno(), 2)

# run your C code here
os.write(1, b"This would normally go to stdout\n")

# put the originals back
os.dup2(orig_stdout_fd, 1)
os.dup2(orig_stderr_fd, 2)
os.close(orig_stdout_fd)
os.close(orig_stderr_fd)
like image 55
Charles Duffy Avatar answered Jan 23 '26 05:01

Charles Duffy