为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕标琳琳 2019-10-29 12:53:23
Python中是否有一种方法可以在不包装如下所示的函数调用的情况下使stdout静音?原始破解代码:from sys import stdoutfrom copy import copysave_stdout = copy(stdout)stdout = open('trash','w')foo()stdout = save_stdout编辑:更正了来自Alex Martelli的代码import syssave_stdout = sys.stdoutsys.stdout = open('trash', 'w')foo()sys.stdout = save_stdout这种方法可行,但效率极低。有有是一个更好的办法。有任何想法吗?
查看完整描述

3 回答

?
慕森王

TA贡献1777条经验 获得超3个赞

stdout假设foo包含print语句,在执行操作时分配变量不会产生任何影响-另一个示例,说明为什么您永远不应该从模块内部导入内容(如此处所做的操作),而始终从模块内部整体导入(然后使用限定名称)。copy顺便说一句,这无关紧要。您的摘要的正确等效项是:


import sys

save_stdout = sys.stdout

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

foo()

sys.stdout = save_stdout

现在,当代码正确时,是使它更优雅或更快速的时候了。例如,您可以使用内存中类似文件的对象代替文件“ trash”:


import sys

import io

save_stdout = sys.stdout

sys.stdout = io.BytesIO()

foo()

sys.stdout = save_stdout

为了优雅起见,上下文是最佳的,例如:


import contextlib

import io

import sys


@contextlib.contextmanager

def nostdout():

    save_stdout = sys.stdout

    sys.stdout = io.BytesIO()

    yield

    sys.stdout = save_stdout

一旦定义了此上下文,对于不需要标准输出的任何块,


with nostdout():

    foo()

更多优化:您只需要使用具有no-op write方法的对象替换sys.stdout 。例如:


import contextlib

import sys


class DummyFile(object):

    def write(self, x): pass


@contextlib.contextmanager

def nostdout():

    save_stdout = sys.stdout

    sys.stdout = DummyFile()

    yield

    sys.stdout = save_stdout

与之前的实现方式相同nostdout。我认为它不会比这更干净或更快速;-)。


查看完整回答
反对 回复 2019-10-29
?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

只是为了补充别人已经说过的内容,Python 3.4引入了contextlib.redirect_stdout上下文管理器。它接受将输出重定向到的文件(类)对象。


重定向到/ dev / null将抑制输出:


In [11]: def f(): print('noise')


In [12]: import os, contextlib


In [13]: with open(os.devnull, 'w') as devnull:

   ....:     with contextlib.redirect_stdout(devnull):

   ....:         f()

   ....:         


In [14]: 

此解决方案可以用作装饰器:


import os, contextlib


def 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_stdout

def 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中


查看完整回答
反对 回复 2019-10-29
?
SMILET

TA贡献1796条经验 获得超4个赞

您为什么认为这效率低下?你测试了吗?顺便说一句,它根本不起作用,因为您正在使用该from ... import语句。sys.stdout可以很好地进行替换,但是不要进行复制,也不要使用临时文件。而是打开空设备:


import sys

import os


def foo():

    print "abc"


old_stdout = sys.stdout

sys.stdout = open(os.devnull, "w")

try:

    foo()

finally:

    sys.stdout.close()

    sys.stdout = old_stdout


查看完整回答
反对 回复 2019-10-29
  • 3 回答
  • 0 关注
  • 704 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信