在 Python 中重定向 FORTRAN(通过 F2PY 调用)输出

发布于 2024-07-23 05:16:09 字数 939 浏览 5 评论 0原文

我正在尝试弄清楚如何重定向某些 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)。

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陈甜 2024-07-30 05:16:09

stdin 和 stdout fd 由 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!"

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!"
深居我梦 2024-07-30 05:16:09

这是我最近编写的一个上下文管理器,它很有用,因为我有一个与 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()

我创建此内容的上下文位于 这篇博文。 我觉得和你的类似。

我在 setup.py 中像这样使用它:

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

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')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文