Как подавить вывод консоли в Python?

Я использую модуль джойстика Pygame/SDL для получения ввода с геймпада. Каждый раз звоню get_hat() метод это печатает на консоль. Это проблематично, так как я использую консоль, чтобы помочь мне отладить, и теперь она затопляется SDL_JoystickGetHat value:0: 60 раз каждую секунду. Есть ли способ, которым я могу отключить это? Либо через опцию в Pygame/SDL, либо запретить вывод на консоль при вызове функции? Я не видел упоминаний об этом в документации Pygame.

edit: Это происходит из-за того, что отладка была включена, когда библиотека SDL была скомпилирована.

9 ответов

Решение

Вот соответствующий блок кода из 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) {

Похоже, проблема с включенной отладкой.

Просто для полноты, вот хорошее решение из блога Дэйва Смита:

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")

Чтобы завершить ответ Чарльза, в python встроены два менеджера контекста, redirect_stdout а также redirect_stderr который вы можете использовать для перенаправления и / или подавления вывода команд в файл или StringIO переменная.

import contextlib

with contextlib.redirect_stdout(None):
    do_thing()

Для более полного объяснения прочитайте документы

Вы можете обойти это, назначив стандартное out/error (я не знаю, к какому типу это относится) нулевому устройству. В Python стандартные файлы out / error sys.stdout/sys.stderrи нулевое устройство os.devnullтак ты делаешь

sys.stdout = os.devnull
sys.stderr = os.devnull

Это должно полностью отключить эти сообщения об ошибках. К сожалению, это также отключит весь вывод консоли. Чтобы обойти это, отключите вывод прямо перед вызовом get_hat() метод, а затем восстановить его, выполнив

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

который восстанавливает стандартные ошибки и ошибки до их первоначального значения.

Основываясь на @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

Полезно (например), чтобы сигнализировать о завершении длительных сценариев.

Я использую pythonw.exe (в Windows) вместо python.exe. В других ОС вы также можете перенаправить вывод в /dev/nul. И для того, чтобы все еще видеть мои выходные данные отладки, я использую модуль регистрации.

Как упоминает Demolishun в ответе на закрытый дубликат вопроса, об этой проблеме есть тема. Этот поток относится к августу 2009 года, и один из разработчиков говорит, что отладочный код был оставлен случайно. Я установил Pygame 1.9.1 из pip, и выходные данные отладки все еще присутствуют.

Чтобы обойти это сейчас, я скачал исходник с 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)
Другие вопросы по тегам