猿问

使Python中的函数标准输出静音,而不会破坏sys.stdout并恢复每个函数调用

Python中是否有一种方法可以在不包装如下所示的函数调用的情况下使stdout静音?


原始破解代码:


from sys import stdout

from copy import copy

save_stdout = copy(stdout)

stdout = open('trash','w')

foo()

stdout = save_stdout

编辑:更正了来自Alex Martelli的代码


import sys

save_stdout = sys.stdout

sys.stdout = open('trash', 'w')

foo()

sys.stdout = save_stdout

这种方法可行,但效率极低。有有是一个更好的办法。有任何想法吗?


慕标琳琳
浏览 705回答 3
3回答

慕森王

stdout假设foo包含print语句,在执行操作时分配变量不会产生任何影响-另一个示例,说明为什么您永远不应该从模块内部导入内容(如此处所做的操作),而始终从模块内部整体导入(然后使用限定名称)。copy顺便说一句,这无关紧要。您的摘要的正确等效项是:import syssave_stdout = sys.stdoutsys.stdout = open('trash', 'w')foo()sys.stdout = save_stdout现在,当代码正确时,是使它更优雅或更快速的时候了。例如,您可以使用内存中类似文件的对象代替文件“ trash”:import sysimport iosave_stdout = sys.stdoutsys.stdout = io.BytesIO()foo()sys.stdout = save_stdout为了优雅起见,上下文是最佳的,例如:import contextlibimport ioimport sys@contextlib.contextmanagerdef nostdout():    save_stdout = sys.stdout    sys.stdout = io.BytesIO()    yield    sys.stdout = save_stdout一旦定义了此上下文,对于不需要标准输出的任何块,with nostdout():    foo()更多优化:您只需要使用具有no-op write方法的对象替换sys.stdout 。例如:import contextlibimport sysclass DummyFile(object):    def write(self, x): pass@contextlib.contextmanagerdef nostdout():    save_stdout = sys.stdout    sys.stdout = DummyFile()    yield    sys.stdout = save_stdout与之前的实现方式相同nostdout。我认为它不会比这更干净或更快速;-)。

有只小跳蛙

只是为了补充别人已经说过的内容,Python 3.4引入了contextlib.redirect_stdout上下文管理器。它接受将输出重定向到的文件(类)对象。重定向到/ dev / null将抑制输出:In [11]: def f(): print('noise')In [12]: import os, contextlibIn [13]: with open(os.devnull, 'w') as devnull:   ....:     with contextlib.redirect_stdout(devnull):   ....:         f()   ....:         In [14]: 此解决方案可以用作装饰器:import os, contextlibdef supress_stdout(func):    def wrapper(*a, **ka):        with open(os.devnull, 'w') as devnull:            with contextlib.redirect_stdout(devnull):                func(*a, **ka)    return wrapper@supress_stdoutdef f():    print('noise')f() # nothing is printed在Python 2和3中都可以使用的另一种可能且偶尔有用的解决方案是将/ dev / null作为参数传递给f并使用函数的file参数重定向输出print:In [14]: def f(target): print('noise', file=target)In [15]: with open(os.devnull, 'w') as devnull:   ....:     f(target=devnull)   ....:     In [16]: 您甚至可以target完全选择:def f(target=sys.stdout):    # Here goes the function definition请注意,您需要from __future__ import print_function在Python 2中

SMILET

您为什么认为这效率低下?你测试了吗?顺便说一句,它根本不起作用,因为您正在使用该from ... import语句。sys.stdout可以很好地进行替换,但是不要进行复制,也不要使用临时文件。而是打开空设备:import sysimport osdef foo():    print "abc"old_stdout = sys.stdoutsys.stdout = open(os.devnull, "w")try:    foo()finally:    sys.stdout.close()    sys.stdout = old_stdout
随时随地看视频慕课网APP

相关分类

Python
我要回答