禁止打印调用(python)

时间:2011-12-05 20:26:55

标签: python printing pygame

有没有办法阻止函数调用print


我正在使用pygame.joystick模块进行我正在进行的游戏。

我创建了一个pygame.joystick.Joystick对象,并在游戏的实际循环中调用其成员函数get_button来检查用户输入。该函数执行我需要它做的所有事情,但问题是它还调用print,这会大大减慢游戏速度。

我可以阻止此次呼叫到print吗?

11 个答案:

答案 0 :(得分:57)

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()。如果要禁用所有打印,请在文件顶部开始阻止。

答案 1 :(得分:46)

基于@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,这在处理异常时尤其重要。

# This is an example of not-so-good solution
# without 'with' context manager statement.
try:
    disable_prints()
    something_throwing()
    # enable_prints() This wouldn't be enough!
except ValueError:
    handle_error()
finally:
    enable_prints() # That's where it needs to go.

如果您忘记finally条款,则print来电不会打印任何内容。使用with语句,这是不可能的。

使用sys.stdout = None是不安全的,因为有人可以调用sys.stdout.write()这样的方法

答案 2 :(得分:4)

不,没有,尤其是大部分PyGame都是用C语言编写的。

但是如果这个函数调用print,那么它就是PyGame bug,你应该报告它。

答案 3 :(得分:2)

我遇到了同样的问题,我没有找到另一个解决方案,而是将程序的输出(我不确切地知道垃圾邮件是否发生在stdout或stderr上)重定向到/dev/null nirvana。

确实,它是开源的,但我没有足够的热情潜入pygame来源 - 以及构建过程 - 以某种方式停止调试垃圾邮件。

编辑:

pygame.joystick module在所有将实际值返回给Python的函数中调用printf

printf("SDL_JoystickGetButton value:%d:\n", value);

不幸的是,您需要对这些内容进行评论并重新编译整个内容。也许所提供的setup.py会比我想象的更容易。你可以试试这个......

答案 4 :(得分:2)

正如@Alexander Chzhen建议的那样,使用上下文管理器比调用一对状态改变函数更安全。

但是,您不需要重新实现上下文管理器 - 它已经在标准库中。您可以将stdoutprint使用的文件对象)与contextlib.redirect_stdout重定向,也可以将stderr重定向到contextlib.redirect_stderr

import os
import contextlib

with open(os.devnull, "w") as f, contextlib.redirect_stdout(f):
    print("This won't be printed.")

答案 5 :(得分:2)

如果要阻止由特定功能进行的打印调用,则可以使用装饰器来解决问题。定义以下装饰器:

# decorater used to block function printing to the console
def blockPrinting(func):
    def func_wrapper(*args, **kwargs):
        # block all printing to the console
        sys.stdout = open(os.devnull, 'w')
        # call the method in question
        value = func(*args, **kwargs)
        # enable all printing to the console
        sys.stdout = sys.__stdout__
        # pass the return value of the method back
        return value

    return func_wrapper

然后将@blockPrinting放在任何函数之前。例如:

# This will print
def helloWorld():
    print("Hello World!")
helloWorld()

# This will not print
@blockPrinting
def helloWorld2():
    print("Hello World!")
helloWorld2()

答案 6 :(得分:2)

如果您使用的是 Jupyter Notebook 或 Colab,请使用:

from IPython.utils import io

with io.capture_output() as captured:
    print("I will not be printed.")

答案 7 :(得分:1)

完全不同的方法是在命令行重定向。如果您使用的是Windows,则表示批处理脚本。在Linux上,bash。

/full/path/to/my/game/game.py > /dev/null
C:\Full\Path\To\My\Game.exe > nul

除非您正在处理多个进程,否则此工作。对于Windows用户,这可能是您正在创建的快捷方式(开始菜单/桌面)。

答案 8 :(得分:1)

我用过的模块打印到stderr。因此,在这种情况下的解决方案是:

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

答案 9 :(得分:0)

基于@Alexander Chzhen解决方案,我在这里介绍了将其应用于具有或不抑制打印的选项的功能的方法。

    import os, sys
    class SuppressPrints:
        #different from Alexander`s answer
        def __init__(self, suppress=True):
            self.suppress = suppress

        def __enter__(self):
            if self.suppress:
                self._original_stdout = sys.stdout
                sys.stdout = open(os.devnull, 'w')

        def __exit__(self, exc_type, exc_val, exc_tb):
            if self.suppress:
                sys.stdout.close()
                sys.stdout = self._original_stdout
    #implementation
    def foo(suppress=True):
        with SuppressPrints(suppress):
            print("It will be printed, or not")

    foo(True)  #it will not be printed
    foo(False) #it will be printed

我希望我可以将我的解决方案添加到亚历山大的回答下面作为评论,但是我没有足够的(50)名声。

答案 10 :(得分:0)

您可以执行一个简单的重定向,这似乎比使用stdout更加安全,而且不会引入任何其他库。

enable_print  = print
disable_print = lambda *x, **y: None

print = disable_print
function_that_has_print_in_it(1)  # nothing is printed

print = enable_print
function_that_has_print_in_it(2)  # printing works again!

注意:这仅在禁用print()函数时有效,并且如果您要对产生输出的其他对象进行调用,则不会禁用所有输出。例如,如果您正在调用一个正在生成它的C库,并将其自身的输出输出到stdout,或者您正在使用intput()。