有没有办法让Python在没有包含像下面这样的函数调用的情况下使stdout静音?
原始破码:
from sys import stdout
from copy import copy
save_stdout = copy(stdout)
stdout = open('trash','w')
foo()
stdout = save_stdout
Run Code Online (Sandbox Code Playgroud)
编辑:更正了Alex Martelli的代码
import sys
save_stdout = sys.stdout
sys.stdout = open('trash', 'w')
foo()
sys.stdout = save_stdout
Run Code Online (Sandbox Code Playgroud)
这种方式有效,但似乎非常低效.有有是一个更好的办法.有任何想法吗?
Ale*_*lli 83
stdout正如你所做的那样分配变量没有任何效果,假设foo包含print语句 - 这是为什么你永远不应该从模块内部导入东西的另一个例子(就像你在这里做的那样),但总是一个模块作为一个整体(然后使用合格的名字).copy顺便说一句,这是无关紧要的.您的代码段的正确等效项是:
import sys
save_stdout = sys.stdout
sys.stdout = open('trash', 'w')
foo()
sys.stdout = save_stdout
Run Code Online (Sandbox Code Playgroud)
现在,当代码正确时,是时候让它更优雅或更快.例如,您可以使用内存中类文件对象而不是文件'trash':
import sys
import io
save_stdout = sys.stdout
sys.stdout = io.BytesIO()
foo()
sys.stdout = save_stdout
Run Code Online (Sandbox Code Playgroud)
对于优雅,上下文是最好的,例如:
import contextlib
import io
import sys
@contextlib.contextmanager
def nostdout():
save_stdout = sys.stdout
sys.stdout = io.BytesIO()
yield
sys.stdout = save_stdout
Run Code Online (Sandbox Code Playgroud)
一旦你定义了这个上下文,对于你不想要一个标准输出的任何一个块,
with nostdout():
foo()
Run Code Online (Sandbox Code Playgroud)
更多优化:您只需要将sys.stdout替换为具有no-op write方法的对象.例如:
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
Run Code Online (Sandbox Code Playgroud)
使用方式与之前的实现方式相同nostdout.我不认为它比这更清洁或更快;-).
vau*_*tah 21
为了补充其他人已经说过的内容,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]:
Run Code Online (Sandbox Code Playgroud)
此解决方案可以适用于装饰器:
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
Run Code Online (Sandbox Code Playgroud)
在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]:
Run Code Online (Sandbox Code Playgroud)
你甚至可以target完全选择:
def f(target=sys.stdout):
# Here goes the function definition
Run Code Online (Sandbox Code Playgroud)
注意,你需要
from __future__ import print_function
Run Code Online (Sandbox Code Playgroud)
在Python 2中.
Phi*_*ipp 15
为什么你认为这是低效的?你测试过吗?顺便说一下,它根本不起作用,因为你正在使用该from ... import语句.替换sys.stdout很好,但不要复制,也不要使用临时文件.改为打开null设备:
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
Run Code Online (Sandbox Code Playgroud)
小智 13
我觉得这个问题是一个更清洁的解决方案.
import sys, traceback
class Suppressor(object):
def __enter__(self):
self.stdout = sys.stdout
sys.stdout = self
def __exit__(self, type, value, traceback):
sys.stdout = self.stdout
if type is not None:
# Do normal exception handling
def write(self, x): pass
Run Code Online (Sandbox Code Playgroud)
用法:
with Suppressor():
DoMyFunction(*args,**kwargs)
Run Code Online (Sandbox Code Playgroud)
Pin*_*en 9
从 python 3.4 开始,redirect_stdout()已经被添加到 contextlib 中
对于 python >= 3.4,应该这样做:
import contextlib
import io
with contextlib.redirect_stdout(io.StringIO()):
foo()
Run Code Online (Sandbox Code Playgroud)
对Alex Martelli的回答略有修改......
这解决了您总是希望抑制stdout函数而不是单独调用函数的情况.
如果foo()多次调用它可能更好/更容易包装函数(装饰它).这样您就可以更改foo一次的定义,而不是在with语句中包含函数的每次使用.
import sys
from somemodule import foo
class DummyFile(object):
def write(self, x): pass
def nostdout(func):
def wrapper(*args, **kwargs):
save_stdout = sys.stdout
sys.stdout = DummyFile()
func(*args, **kwargs)
sys.stdout = save_stdout
return wrapper
foo = nostdout(foo)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
35407 次 |
| 最近记录: |