13

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 で出力をリダイレクトするデファクトの方法ですが、この場合はうまくいかないようです (つまり、とにかく出力が表示されます)。

2002 年のメーリング リストの投稿で、「pts デバイスからメッセージを読み取ることができます。たとえば、ttysnoop がこれを行います」という内容を見つけました。ttysnoop に関する情報をオンラインで見つけるのはかなり難しいようです (ここ数年更新されていないと思います。たとえば、「ttysnoop」に関する Google での最初の結果には、tarball、RPM、および .deb へのデッド リンクしかありません。 )、そしてOS X への移植を求めるこの要求に対して、「うまくいきません。作成できない Linux 固有の utmp 関数が必要です。」という応答を受け取りました。

出力をリダイレクトする方法についての提案をお待ちしています (ttysnoop を使用する必要はありません)。

ありがとう!

4

2 に答える 2

24

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

pymssqlの作業中に同様の問題を抱えていたので、最近書いて便利だと思ったコンテキストマネージャーを次に示します。ファイル記述子アプローチも使用しましたが、コンテキスト マネージャーを使用しました。これが私が思いついたものです:distutils.ccompiler.CCompiler.has_function

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')
于 2013-07-19T18:59:26.557 に答える