如何阻止调用print?
有没有办法阻止一个函数调用 print
呢?
我正在为一个游戏使用 pygame.joystick
模块。
我创建了一个 pygame.joystick.Joystick
对象,然后在游戏的主循环中调用它的成员函数 get_button
来检查用户输入。这个函数能完成我需要的所有操作,但问题是它还调用了 print
,这让游戏变得很慢。
我能否 阻止 这个 print
的调用呢?
15 个回答
正如@Alexander Chzhen所建议的,使用上下文管理器会比直接调用一对改变状态的函数更安全。
不过,你不需要自己重新实现上下文管理器,因为它已经在标准库里了。你可以用contextlib.redirect_stdout
来重定向stdout
(也就是print
使用的文件对象),还可以用contextlib.redirect_stderr
来重定向stderr
。
import os
import contextlib
with open(os.devnull, "w") as f, contextlib.redirect_stdout(f):
print("This won't be printed.")
你可以通过定义自己的包装上下文管理器来封装这个逻辑:
import os
import contextlib
@contextlib.contextmanager
def suppress_print():
with open(os.devnull, "w") as f, contextlib.redirect_stdout(f):
yield
print("This will be printed")
with suppress_print():
print("This will not")
print("Printing works outside the with-statement")
使用 with
根据 @FakeRainBrigand 的解决方案,我建议一个更安全的方法:
import os, sys
class HiddenPrints:
def __enter__(self):
self._original_stdout = sys.stdout
sys.stdout = open(os.devnull, 'w')
def __exit__(self, exc_type, exc_val, exc_tb):
sys.stdout.close()
sys.stdout = self._original_stdout
然后你可以这样使用:
with HiddenPrints():
print("This will not be printed")
print("This will be printed as before")
这样做更安全,因为你不会忘记重新启用标准输出(stdout),这在处理异常时尤其重要。
不好的做法:没有 with
下面的例子使用了之前回答中提到的启用/禁用打印功能。
想象一下,有一段代码可能会抛出异常。我们必须使用 finally
语句来确保无论如何都能启用打印。
try:
disable_prints()
something_throwing()
enable_prints() # This will not help in case of exception
except ValueError as err:
handle_error(err)
finally:
enable_prints() # That's where it needs to go.
如果你忘记了 finally
这个部分,你的 print
调用就再也不会输出任何内容了。
使用 with
语句更安全,因为它可以确保打印会被重新启用。
注意:使用 sys.stdout = None
是不安全的,因为可能会有人调用像 sys.stdout.write()
这样的函数。
Python 允许你用任何文件对象来替代标准输出(stdout)。这在不同的平台上都应该能正常工作,并且可以写入空设备。
import sys, os
# Disable
def blockPrint():
sys.stdout = open(os.devnull, 'w')
# Restore
def enablePrint():
sys.stdout = sys.__stdout__
print 'This will print'
blockPrint()
print "This won't"
enablePrint()
print "This will too"
如果你不想让某个函数打印内容,可以在它之前调用 blockPrint()
,然后在你想让它继续打印的时候调用 enablePrint()
。如果你想禁用 所有 的打印,可以在文件的开头就开始阻止打印。