我正在试图弄清楚如何使用F2PY从我为其生成Python接口的一些FORTRAN代码重定向输出。我试过了:
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中重定向输出的事实上的方法,但在这种情况下似乎不起作用(即,无论如何都会显示输出)。
我确实发现a mailing list post from 2002说“有可能从pts设备读取消息,例如ttysnoop会这样做”。关于ttysnoop的信息似乎很难在网上找到(我不认为它已经在几年内更新;例如,the first result on Google for "ttysnoop"只有到tarball,RPM和.deb的死链接)和{ {3}}收到回复“没有运气,它需要一些我无法创建的linux特定的utmp函数。”
我愿意接受有关如何重定向输出的任何建议(它不必使用ttysnoop)。
谢谢!
答案 0 :(得分:18)
stdin和stdout 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!"
答案 1 :(得分:4)
这是我最近编写的context manager并发现有用,因为我在处理distutils.ccompiler.CCompiler.has_function
时遇到与pymssql类似的问题。我也使用了文件描述符方法,但我使用了context manager。这就是我想出的:
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()
我创建此内容的上下文位于this blog post。我认为与你的相似。
我在setup.py
:
with stdchannel_redirected(sys.stderr, os.devnull):
if compiler.has_function('clock_gettime', libraries=['rt']):
libraries.append('rt')