如何在Python中抑制控制台输出?

问题描述 投票:0回答:10

我正在使用 Pygame/SDL 的操纵杆模块从游戏手柄获取输入。每次我调用它的

get_hat()
方法时,它都会打印到控制台。这是有问题的,因为我使用控制台来帮助我调试,现在它每秒被
SDL_JoystickGetHat value:0:
淹没 60 次。有什么方法可以禁用此功能吗?是通过 Pygame/SDL 中的选项还是在函数调用时抑制控制台输出?我在 Pygame 文档中没有看到提到这一点。

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

python sdl pygame
10个回答
71
投票

为了完整起见,这是来自 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")

45
投票

为了完成查尔斯的回答,Python 中内置了两个上下文管理器,

redirect_stdout
redirect_stderr
,您可以使用它们来重定向和/或抑制命令输出到文件或
StringIO
变量。

import contextlib

with contextlib.redirect_stdout(None):
    do_thing()

如需更完整的解释,请阅读文档

快速更新: 在某些情况下,传递

None
可能会引发一些引用错误(例如
keras.models.Model.fit
调用
sys.stdout.write
这会出现问题),在这种情况下传递
io.StringIO()
os.devnull


23
投票

您可以通过将标准输出/错误(我不知道它会指向哪一个)分配给空设备来解决这个问题。在 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__

将标准输出和错误恢复为其原始值。


6
投票

以@charleslparker 的answer为基础:

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

可用于(例如)发出长时间运行脚本完成的信号。


5
投票

这是来自 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) {

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


2
投票

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


1
投票

正如 Demolishun 在一个已关闭的重复问题的 answer 中提到的,有一个 thread 正在谈论这个问题。该线程来自 2009 年 8 月,其中一位开发人员表示“调试代码是意外留下的”。我已经从 pip 安装了 Pygame 1.9.1 并且调试输出仍然存在。 为了暂时解决这个问题,我从 pygame.org 下载了源代码,从 src/joystick.c 中删除了打印语句并编译了代码。

我使用的是 OS X 10.7.5,因为它物有所值。


0
投票

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

问候
最大


0
投票
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)



0
投票
In python, how to capture the stdout from a c++ Shared Library to a variable

下面的代码为我解决了不朽的 PyTorch 警告问题:

import sys import os class SuppressStream(object): def __init__(self): self.orig_stream_fileno = sys.stderr.fileno() def __enter__(self): self.orig_stream_dup = os.dup(self.orig_stream_fileno) self.devnull = open(os.devnull, 'w') os.dup2(self.devnull.fileno(), self.orig_stream_fileno) def __exit__(self, type, value, traceback): os.close(self.orig_stream_fileno) os.dup2(self.orig_stream_dup, self.orig_stream_fileno) os.close(self.orig_stream_dup) self.devnull.close() with SuppressStream(): torch.onnx.export( model, ...

	
© www.soinside.com 2019 - 2024. All rights reserved.