13

我试图弄清楚如何重定向一些 FORTRAN 代码的输出,我已经使用 F2PY 为其生成了 Python 接口。我试过了:

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

这是在 Python 中重定向输出的事实上的方法,但在这种情况下它似乎不起作用(即,无论如何都会显示输出)。

我确实找到了一个 2002 年的邮件列表帖子,上面写着“可以从 pts 设备读取消息,例如 ttysnoop 就是这样做的”。ttysnoop 上的信息似乎很难在网上找到(我认为它已经有好几年没有更新了;例如,Google 上关于“ttysnoop”的第一个结果只有指向 tarball、RPM 和 .deb 的死链接),并且此 OS X 端口请求收到了响应“不走运,它需要一些我无法创建的特定于 linux 的 utmp 函数。”

我愿意接受有关如何重定向输出的任何建议(它不必使用 ttysnoop)。

谢谢!

4

2 回答 2

24

标准输入和标准输出 fds 被 C 共享库继承。

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!"
于 2009-06-10T21:33:26.310 回答
6

这是我最近编写并发现有用的上下文管理器distutils.ccompiler.CCompiler.has_function,因为我在处理pymssql时遇到了类似的问题。我也使用了文件描述符方法,但我使用了上下文管理器。这是我想出的:

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()

我创建它的原因在此博客文章中。我觉得和你的差不多。

我在 a 中这样使用它setup.py

with stdchannel_redirected(sys.stderr, os.devnull):
    if compiler.has_function('clock_gettime', libraries=['rt']):
        libraries.append('rt')
于 2013-07-19T18:59:26.557 回答