Redirecting FORTRAN (called via F2PY) output in Python
Question: I'm trying to figure out how to redirect output from some FORTRAN code for
which I've generated a Python interface by using F2PY. I've tried:

    
    
    from fortran_code import fortran_function
    stdout_holder = sys.stdout
    stderr_holder = sys.stderr
    sys.stdout = file("/dev/null","w")
    fortran_function()
    sys.stdout.close()
    sys.stderr.close()
    sys.stdout = stdout_holder
    sys.stderr = stderr_holder
    

This is the de facto method of redirecting output in Python, but it doesn't
seem to work in this case (i.e., the output is displayed anyway).

I did find [a mailing list post from 2002](http://cens.ioc.ee/pipermail/f2py-
users/2002-November/000352.html) saying that "It is possible to read messages
from pts devices, e.g. ttysnoop does this". Information on ttysnoop seems to
be pretty difficult to find online (I don't think it's been updated in quite a
few years; for example, [the first result on Google for
"ttysnoop"](http://www.linuxhelp.net/guides/ttysnoop/) has only dead links to
tarballs, RPMs, and .deb's), and [this request for a port to OS
X](http://macosx.forked.net/bbarchive/forum5/000008.html) received the
response "No luck, it requires some linux specific utmp functions which I
can't create."

I'm open to any suggestions on how to redirect the output (it doesn't have to
use ttysnoop).

Thanks!


Answer: The stdin and stdout fds are being inherited by the C shared library.

    
    
    from fortran_code import fortran_function
    import os
    
    print "will run fortran function!"
    
    # open 2 fds
    null_fds = [os.open(os.devnull, os.O_RDWR) for x in xrange(2)]
    # save the current file descriptors to a tuple
    save = os.dup(1), os.dup(2)
    # put /dev/null fds on 1 and 2
    os.dup2(null_fds[0], 1)
    os.dup2(null_fds[1], 2)
    
    # *** run the function ***
    fortran_function()
    
    # restore file descriptors so I can print the results
    os.dup2(save[0], 1)
    os.dup2(save[1], 2)
    # close the temporary fds
    os.close(null_fds[0])
    os.close(null_fds[1])
    
    print "done!"
    

