我有一个使用一些闭源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()
这个方法“相当不错”。它抑制了那些混乱我的脚本的无用函数的输出。在测试中,我发现它也允许引发异常和一些记录器日志的打印通过,我不是完全清楚其中的原因。我认为这可能与这些消息何时发送到标准输出/标准错误流有关(我认为这是在上下文管理器退出之后发生的)。如果有人可以确认这一点,我会很感兴趣听到详情...
sys.stdout
设置为文件而不是StringIO()
吗?例如:sys.stdout = open('log.txt','w')
。 - carmenism__exit__
中关闭所有文件描述符。如果不关闭self.save_fds
中的fd,则每次调用此上下文管理器都会泄漏两个文件描述符,导致长时间运行的进程中的文件描述符耗尽。 - randlet