如何阻止打印呼叫?

2025-02-21 08:48:00
admin
原创
27
摘要:问题描述:有没有办法阻止函数调用print?我正在使用该pygame.joystick模块开发一款游戏。我创建了一个pygame.joystick.Joystick对象,并在游戏的实际循环中调用其成员函数get_button来检查用户输入。该函数完成了我需要它做的所有事情,但问题是它还调用了print,这大大...

问题描述:

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


我正在使用该pygame.joystick模块开发一款游戏。

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

我可以屏蔽这个来电吗print


解决方案 1:

使用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()

解决方案 2:

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()希望其继续时调用。如果您想要禁用所有打印,请在文件顶部开始阻止。

解决方案 3:

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

但是,您不需要重新实现上下文管理器 - 它已经在标准库中了。您可以使用重定向(使用的文件对象) ,也可以使用重定向stdout(使用的文件对象) 。print`contextlib.redirect_stdoutstderrcontextlib.redirect_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")

解决方案 4:

如果要阻止特定函数的打印调用,则可以使用装饰器来提供更简洁的解决方案。定义以下装饰器:

# 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()

Jupyter Notebooks可能需要将func_wrapper代码替换为:

from IPython.utils.io import capture_output

def func_wrapper(*args, **kwargs):
    with capture_output():
        value = func(*args, **kwargs)
    return value

解决方案 5:

如果你正在使用 Jupyter Notebook 或 Colab,请使用以下命令:

from IPython.utils import io

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

解决方案 6:

完全不同的方法是在命令行上重定向。如果你使用的是 Windows,这意味着批处理脚本。在 Linux 上,则是 bash。

/full/path/to/my/game/game.py > /dev/null
C:FullPathToMyGame.exe > nul

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

解决方案 7:

您可以进行一个简单的重定向,这看起来比弄乱标准输出要安全得多,并且不会引入任何额外的库。

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()。

解决方案 8:

我遇到了同样的问题,我没有找到其他解决方案,而是将程序的输出(我不知道垃圾邮件是发生在 stdout 还是 stderr 上)重定向到/dev/nullnirvana。

确实,它是开源的,但我没有足够的热情去深入pygame研究源代码和构建过程,以某种方式阻止调试垃圾邮件。

编辑 :

pygame.joystick模块在所有函数中都调用了printf将实际值返回给 Python:

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

不幸的是,您需要注释掉这些内容并重新编译整个内容。也许提供的内容setup.py会比我想象的更容易。您可以尝试这个...

解决方案 9:

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

但是如果此函数调用了 print,那么它就是 PyGame 错误,你应该报告它。

解决方案 10:

"stop a function from calling print"
# import builtins
# import __builtin__ # python2, not test
printenabled = False
def decorator(func):
    def new_func(*args,**kwargs):
        if printenabled:
            func("print:",*args,**kwargs)
    return new_func
print = decorator(print) # current file
# builtins.print = decorator(builtins.print)  # all files
# __builtin__.print = decorator(__builtin__.print) # python2

import sys
import xxxxx
def main():
    global printenabled
    printenabled = True
    print("1 True");
    printenabled = False
    print("2 False");
    printenabled = True
    print("3 True");
    printenabled = False
    print("4 False");
if __name__ == '__main__':
    sys.exit(main())

#output
print: 1 True
print: 3 True

https://stackoverflow.com/a/27622201

解决方案 11:

更改 print() 函数的文件对象的值。默认情况下,它是sys.stdout,我们可以通过以下方式写入空设备open(os.devnull, 'w')

import os, sys

mode = 'debug' #'prod'

if mode == 'debug':
    fileobj = sys.stdout
else:
    fileobj = open(os.devnull,'w')

print('Hello Stackoverflow', file = fileobj)

解决方案 12:

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

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

解决方案 13:

基于@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)来这样做。

解决方案 14:

如果您想使用变量启用/禁用打印,您可以调用辅助函数来代替打印,例如 printe(此名称只是为了方便)

def printe(*what_to_print):
if prints_enable:
    string = ""
    for items in what_to_print:
        string += str(items) + " "
    print(string)

解决方案 15:

定义一个新的打印函数,首先启用打印,然后打印输出,然后再次禁用打印。

def Print (*output):
   enablePrint()
   print (output)
   disablePrint()

使用上述“安全”启用/禁用功能之一

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1343  
  信创产业的蓬勃发展推动着各行业数字化转型加速,数据库迁移作为其中关键一环,面临诸多挑战。信创数据库迁移旨在将传统数据库平稳过渡到信创环境,以满足自主可控、安全可靠的需求。这一过程涉及技术、业务等多方面因素,稍有不慎就可能出现各种问题,影响业务的正常运行。深入探讨信创数据库迁移过程中的常见问题及解决方案,对于保障迁移工作...
2027年信创国产化   41  
  随着信息技术的飞速发展,信创国产化成为了国家战略的重要组成部分。国产化信创产品名录涵盖了众多领域,其在各个关键应用场景中发挥着重要作用。而信创国产化操作系统作为其中的核心环节,具备五大核心优势,为我国信息技术产业的自主可控发展提供了坚实支撑。关键应用场景之办公领域在办公领域,国产化信创产品有着广泛且深入的应用。如今,越...
国产信创系统   37  
  随着信息技术的飞速发展,信创国产化操作系统在政府部门的推广应用具有重要的战略意义。它不仅关乎国家信息安全,更是推动国内信息技术产业自主创新、实现科技自立自强的关键举措。在当前复杂的国际形势下,政府部门积极推广信创国产化操作系统,对于保障国家政务信息的安全稳定运行,提升信息技术的自主可控能力,具有不可替代的重要作用。推广...
信创产品有哪些   28  
  在企业数字化转型的进程中,信创数据库解决方案的选择至关重要。它不仅关乎企业数据的安全存储与管理,更影响着企业业务的稳定运行与未来发展。合适的信创数据库能够助力企业在复杂多变的市场环境中提升竞争力,保障数据主权与安全。然而,面对市场上众多的信创数据库产品和解决方案,企业往往感到困惑,不知如何做出正确的选择。接下来,我们将...
信创电脑   24  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用