雇用主から提供されたクローズドボックスの Python 関数 (つまり、これらの関数を編集できない) を使用する Python スクリプトがあります。これらの関数を呼び出すと、抑制したい Linux 端末に出力が出力されます。stdout / stderr をリダイレクトしようとしました;
orig_out = sys.stdout
sys.stdout = StringIO()
rogue_function()
sys.stdout = orig_out
しかし、これは出力をキャッチできません。Python経由で呼び出している関数(上記の rogue_function() )は、実際に印刷を行っているコンパイル済みCコードの実際のラッパーだと思います。
関数 (および関数が呼び出すサブ関数) によって stdout / stderr に渡された任意の印刷の「ディープ キャプチャ」を実行できる方法を知っている人はいますか?
更新:
以下の選択した回答で概説されている方法を採用し、stdoutとstderrを抑制するコンテキストマネージャーを作成しました。
# Define a context manager to suppress stdout and stderr.
class suppress_stdout_stderr(object):
'''
A context manager for doing a "deep suppression" of stdout and stderr in
Python, i.e. will suppress all print, even if the print originates in a
compiled C/Fortran sub-function.
This will not suppress raised exceptions, since exceptions are printed
to stderr just before a script exits, and after the context manager has
exited (at least, I think that is why it lets exceptions through).
'''
def __init__(self):
# Open a pair of null files
self.null_fds = [os.open(os.devnull,os.O_RDWR) for x in range(2)]
# Save the actual stdout (1) and stderr (2) file descriptors.
self.save_fds = [os.dup(1), os.dup(2)]
def __enter__(self):
# Assign the null pointers to stdout and stderr.
os.dup2(self.null_fds[0],1)
os.dup2(self.null_fds[1],2)
def __exit__(self, *_):
# Re-assign the real stdout/stderr back to (1) and (2)
os.dup2(self.save_fds[0],1)
os.dup2(self.save_fds[1],2)
# Close all file descriptors
for fd in self.null_fds + self.save_fds:
os.close(fd)
これを使用するには、次のようにします。
with suppress_stdout_stderr():
rogue_function()
これは「かなり」うまくいきます。私のスクリプトを混乱させていた不正な機能からの出力を抑制します。テスト中に、発生した例外とロガーの出力を通過できることに気付きましたが、その理由は完全にはわかりません。これらのメッセージが stdout / stderr に送信されるときに何か関係があると思います (コンテキストマネージャーが終了した後に発生すると思います)。誰かがこれを確認できるなら、私は詳細を聞くことに興味があります...