一尘不染

从Python函数禁止stdout / stderr打印

python

我有一个Python脚本正在使用我的雇主提供的某些封闭式Python函数(即我无法编辑这些函数)。当我调用这些函数时,它们会将输出打印到我想抑制的Linux终端上。我试过通过重定向标准输出/标准错误;

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有关(我认为这是在上下文管理器退出之后发生的)。如果有人可以确认这一点,我将有兴趣听详细信息…


阅读 198

收藏
2020-12-20

共1个答案

一尘不染

这种方法(通过相关的侧边栏找到)可能有效。它在sys.stdout等中重新分配文件描述符,而不仅仅是包装。

2020-12-20