在Python中静默函数的stdout,而不破坏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
这种方式有效,但似乎效率非常低。 必须有更好的方法。有什么想法吗?
Is there a way in Python to silence stdout without wrapping a function call like following?
Original Broken Code:
from sys import stdout
from copy import copy
save_stdout = copy(stdout)
stdout = open('trash','w')
foo()
stdout = save_stdout
Edit: Corrected code from Alex Martelli
import sys
save_stdout = sys.stdout
sys.stdout = open('trash', 'w')
foo()
sys.stdout = save_stdout
That way works but appears to be terribly inefficient. There has to be a better way. Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
假设
foo
包含print
语句,按照您所做的那样分配stdout
变量没有任何效果 - 这是为什么您永远不应该的另一个例子从模块内部导入内容(正如您在此处所做的那样),但始终将模块作为一个整体(然后使用限定名称)。顺便说一下,copy
是无关紧要的。您的代码片段的正确等效项是:现在,当代码正确时,就是让它变得更优雅或更快的时候了。例如,您可以使用内存中类似文件的对象来代替文件“垃圾”:
为了优雅,上下文是最好的,例如:
一旦定义了此上下文,对于其中的任何块您不需要标准输出,
更多优化:您只需将 sys.stdout 替换为具有无操作
write
方法的对象。例如:使用与之前的
nostdout
实现相同的方式。我认为没有比这更干净或更快的了;-)。Assigning the
stdout
variable as you're doing has no effect whatsoever, assumingfoo
containsprint
statements -- yet another example of why you should never import stuff from inside a module (as you're doing here), but always a module as a whole (then use qualified names). Thecopy
is irrelevant, by the way. The correct equivalent of your snippet is:Now, when the code is correct, is the time to make it more elegant or fast. For example, you could use an in-memory file-like object instead of file 'trash':
for elegance, a context is best, e.g:
once you have defined this context, for any block in which you don't want a stdout,
More optimization: you just need to replace sys.stdout with an object that has a no-op
write
method. For example:to be used the same way as the previous implementation of
nostdout
. I don't think it gets any cleaner or faster than this;-).只是为了补充其他人已经说过的内容,Python 3.4 引入了
contextlib .redirect_stdout
上下文管理器。它接受一个文件(类似)对象,输出将被重定向到该对象。重定向到 /dev/null 将抑制输出:
如果包装的代码不直接写入
sys.stdout
,您可以使用更简单这个解决方案可以适应用作装饰器:
另一种可能且偶尔有用的解决方案可以在 Python 2 和 3 中工作,是将 /dev/null 作为参数传递给
f
并使用print
函数:您甚至可以使
target
完全可选:您需要这样做。
注意,在 Python 2 中
Just to add to what others already said, Python 3.4 introduced the
contextlib.redirect_stdout
context manager. It accepts a file(-like) object to which the output is to be redirected.Redirecting to /dev/null will suppress the output:
If the wrapped code doesn't write to
sys.stdout
directly, you can use the simplerThis solution can be adapted to be used as a decorator:
Another possible and occasionally useful solution that will work in both Python 2 and 3 is to pass /dev/null as an argument to
f
and redirect the output using thefile
argument of theprint
function:You can even make
target
completely optional:Note, you'll need to
in Python 2.
我很晚才提出这个问题,我认为这是一个更干净的解决方案。
用法:
Chiming in very late to this with what I thought was a cleaner solution to this problem.
Usage:
redirect_stdout() 自 python 3.4 起已添加到 contextlib
对于 python >= 3.4,这应该可以做到:
redirect_stdout() has been added to contextlib since python 3.4
For python >= 3.4, this should do it:
为什么你认为这是低效的?您测试了吗?顺便说一句,它根本不起作用,因为您正在使用
from ... import
语句。替换 sys.stdout 就可以了,但不要复制,也不要使用临时文件。打开空设备:
Why do you think this is inefficient? Did you test it? By the way, it does not work at all because you are using the
from ... import
statement.Replacing
sys.stdout
is fine, but don't make a copy and don't use a temporary file. Open the null device instead:对 Alex Martelli 的回答...
这解决了您始终希望抑制函数的
stdout
而不是单独调用该函数的情况。如果
foo()
被多次调用,包装函数(装饰它)可能会更好/更容易。这样,您就可以更改 foo 的定义一次,而不是将该函数的每次使用都包含在 with 语句中。A slight modification to Alex Martelli's answer...
This addresses the case where you always want to suppress
stdout
for a function instead of individual calls to the function.If
foo()
was called many times would it might be better/easier to wrap the function (decorate it). This way you change the definition offoo
once instead of encasing every use of the function in a with-statement.通过进一步概括,您可以获得一个很好的装饰器,它可以捕获输出甚至返回它:
By generalizing even more, you can get a nice decorator that can capture the ouput and even return it:
我认为没有比这更干净或更快的了;-)
呸!我想我可以做得更好一点:-D
这达到了我最初想要的,正常抑制输出,但如果抛出错误则显示抑制的输出。
I don't think it gets any cleaner or faster than this;-)
Bah! I think I can do a little better :-D
Which gets to what I wanted originally, to suppress output normally but to show the suppressed output if an error was thrown.