如何阻止调用print?

138 投票
15 回答
173102 浏览
提问于 2025-04-17 07:45

有没有办法阻止一个函数调用 print 呢?


我正在为一个游戏使用 pygame.joystick 模块。

我创建了一个 pygame.joystick.Joystick 对象,然后在游戏的主循环中调用它的成员函数 get_button 来检查用户输入。这个函数能完成我需要的所有操作,但问题是它还调用了 print,这让游戏变得很慢。

我能否 阻止 这个 print 的调用呢?

15 个回答

78

正如@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")
162

使用 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() 这样的函数。

166

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()。如果你想禁用 所有 的打印,可以在文件的开头就开始阻止打印。

撰写回答