繁体   English   中英

如何在 Python 中抑制控制台 output?

[英]How to suppress console output in Python?

我正在使用 Pygame/SDL 的操纵杆模块从游戏手柄获取输入。 每次我调用它的get_hat()方法时,它都会打印到控制台。 这是有问题的,因为我使用控制台来帮助我调试,现在它每秒被SDL_JoystickGetHat value:0: 60 次淹没。 有什么办法可以禁用它吗? 是通过 Pygame/SDL 中的选项还是在 function 调用时抑制控制台 output? 我在 Pygame 文档中没有看到这一点。

编辑:原来这是由于在编译 SDL 库时打开了调试。

为了完整起见,这里有一个来自Dave Smith 博客的不错的解决方案:

from contextlib import contextmanager
import sys, os

@contextmanager
def suppress_stdout():
    with open(os.devnull, "w") as devnull:
        old_stdout = sys.stdout
        sys.stdout = devnull
        try:  
            yield
        finally:
            sys.stdout = old_stdout

有了这个,您可以在任何想要抑制输出的地方使用上下文管理:

print("Now you see it")
with suppress_stdout():
    print("Now you don't")

为了完成 charles 的回答,python 中内置了两个上下文管理器, redirect_stdoutredirect_stderr ,您可以使用它们将命令输出重定向和/或禁止输出到文件或StringIO变量。

import contextlib

with contextlib.redirect_stdout(None):
    do_thing()

有关更完整的解释,请阅读文档

快速更新:在某些情况下,传递None可能会引发一些引用错误(例如keras.models.Model.fit调用sys.stdout.write这将是有问题的),在这种情况下传递io.StringIO()os.devnull

您可以通过将标准输出/错误(我不知道它将分配给哪个)来解决此问题。 在 Python 中,标准输出/错误文件是sys.stdout / sys.stderr ,而空设备是os.devnull ,所以你这样做

sys.stdout = open(os.devnull, "w")
sys.stderr = open(os.devnull, "w")

这应该完全禁用这些错误消息。 不幸的是,这也会禁用所有控制台输出。 为了解决这个问题,在调用get_hat()方法之前禁用输出,然后通过执行恢复它

sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__

它将标准输出和错误恢复到它们的原始值。

这是来自 joystick.c 的相关代码块(通过 SVN 在http://svn.seul.org/viewcvs/viewvc.cgi/trunk/src/joystick.c?view=markup&revision=2652&root=PyGame

    value = SDL_JoystickGetHat (joy, _index);
#ifdef DEBUG
    printf("SDL_JoystickGetHat value:%d:\n", value);
#endif
    if (value & SDL_HAT_UP) {

看起来像是打开调试的问题。

我使用 pythonw.exe(在 Windows 上)而不是 python.exe。 在其他操作系统中,您还可以将输出重定向到 /dev/nul。 为了仍然看到我的调试输出,我使用了日志记录模块。

基于@charleslparker 的回答

from contextlib import contextmanager
import sys, os

@contextmanager
def suppress_stdout():
    with open(os.devnull, "w") as devnull:
        old_stdout = sys.stdout
        sys.stdout = devnull
        try:  
            yield
        finally:
            sys.stdout = old_stdout

print("Now you see it")
with suppress_stdout():
    print("Now you don't")

测试

>>> with suppress_stdout():
        os.system('play /mnt/Vancouver/programming/scripts/PHASER.WAV')

/mnt/Vancouver/programming/scripts/PHASER.WAV:

 File Size: 1.84k     Bit Rate: 90.4k
  Encoding: Unsigned PCM  
  Channels: 1 @ 8-bit    
Samplerate: 11025Hz      
Replaygain: off         
  Duration: 00:00:00.16  

In:100%  00:00:00.16 [00:00:00.00] Out:1.79k [!=====|=====!]        Clip:0    
Done.

使用它来完全抑制os.system()输出:

>>> with suppress_stdout():
        os.system('play /mnt/Vancouver/programming/scripts/PHASER.WAV >/dev/null 2>&1')
>>> ## successfully executed

>>> import time
>>> with suppress_stdout():
        for i in range(3):
                os.system('play /mnt/Vancouver/programming/scripts/PHASER.WAV >/dev/null 2>&1')
                time.sleep(0.5) 
>>> ## successfully executed

有用(例如)表示长时间运行的脚本完成。

正如Demolishun在对一个封闭的重复问题的回答中提到的那样,有一个线程在讨论这个问题。 该线程来自 2009 年 8 月,其中一位开发人员说调试代码是偶然留下的 我已经从 pip 安装了 Pygame 1.9.1 并且调试输出仍然存在。

为了暂时解决这个问题,我从 pygame.org 下载了源代码,从 src/joystick.c 中删除了打印语句并编译了代码。

我在 OS X 10.7.5 上是为了它的价值。

如果你在 Debian 或 Ubuntu 机器上,你可以简单地重新编译 pygame 而没有消息。

cd /tmp
sudo apt-get build-dep pygame
apt-get source pygame
vim pygame-1.9.1release+dfsg/src/joystick.c
# search for the printf("SDL.. messages and put a // in front
apt-get source --compile pygame
sudo dpkg -i python-pygame_1.9.1release+dfsg-9ubuntu1_amd64.deb

问候麦克斯

使用os.devnull的解决方案可能会导致多处理同步问题 - 因此多个进程将等待同一资源。 至少这是我在windows遇到的。

以下解决方案可能更好:


class DummyOutput(object):
    def __init__(self, *args, **kwargs):
        pass

    def write(self, *args, **kwargs):
        pass


class suppress_stdout_stderr(object):
    def __init__(self):
        self.stdout = sys.stdout
        self.stderr = sys.stderr

    def __enter__(self, *args, **kwargs):
        out = DummyOutput()
        sys.stdout = out
        sys.stderr = out

    def __exit__(self, *args, **kwargs):
        sys.stdout = self.stdout
        sys.stderr = self.stderr


with suppress_stdout_stderr():
    print(123, file=sys.stdout)
    print(123, file=sys.stderr)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM