Redirecting FORTRAN (called via F2PY) output in Python

12,660

Solution 1

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!"

Solution 2

Here's a context manager that I recently wrote and found useful, because I was having a similar problem with distutils.ccompiler.CCompiler.has_function while working on pymssql. I also used the file descriptor approach but I used a context manager. Here's what I came up with:

import contextlib


@contextlib.contextmanager
def stdchannel_redirected(stdchannel, dest_filename):
    """
    A context manager to temporarily redirect stdout or stderr

    e.g.:


    with stdchannel_redirected(sys.stderr, os.devnull):
        if compiler.has_function('clock_gettime', libraries=['rt']):
            libraries.append('rt')
    """

    try:
        oldstdchannel = os.dup(stdchannel.fileno())
        dest_file = open(dest_filename, 'w')
        os.dup2(dest_file.fileno(), stdchannel.fileno())

        yield
    finally:
        if oldstdchannel is not None:
            os.dup2(oldstdchannel, stdchannel.fileno())
        if dest_file is not None:
            dest_file.close()

The context for why I created this is at this blog post. Similar to yours I think.

I use it like this in a setup.py:

with stdchannel_redirected(sys.stderr, os.devnull):
    if compiler.has_function('clock_gettime', libraries=['rt']):
        libraries.append('rt')
Share:
12,660

Related videos on Youtube

Samir Unni
Author by

Samir Unni

Updated on July 20, 2020

Comments

  • Samir Unni
    Samir Unni over 3 years

    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 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" has only dead links to tarballs, RPMs, and .deb's), and this request for a port to OS X 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!

    • habanoz
      habanoz almost 15 years
      Are you sure the fortran output isn't going to stderr instead of stdout?
  • Samir Unni
    Samir Unni almost 15 years
    Will this suppress stderr as well? If not, how can that be accomplished?
  • nosklo
    nosklo almost 15 years
    @aberration: dunno, have you tested it with any fortran programs that write to stderr?
  • josliber
    josliber over 6 years
    Thanks for this very helpful answer. When I added this code to a script that needed to redirect output many times as part of a loop, I noticed that I was leaking file descriptors. I believe you also need os.close(save[0]) and os.close(save[1]) at the end to prevent the leak.
  • Sibbs Gambling
    Sibbs Gambling over 5 years
    Works like charm, but what is FDS short for?
  • nosklo
    nosklo over 5 years
    @SibbsGambling File Descriptors

Related