Подавить звонки на печать (python) - PullRequest
47 голосов
/ 06 декабря 2011

Есть ли способ остановить функцию от вызова print?


Я использую модуль pygame.joystick для игры, над которой я работаю.

Я создал объект pygame.joystick.Joystick и в реальном цикле игры вызываю его функцию-член get_button для проверки ввода пользователя. Функция делает все, что мне нужно, но проблема в том, что она также вызывает print, что значительно замедляет игру.

Могу ли я заблокировать этот вызов print?

Ответы [ 9 ]

61 голосов
/ 06 декабря 2011

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(), если хотите продолжить.,Если вы хотите отключить все печать, начните блокировку в верхней части файла.

48 голосов
/ 14 августа 2017

На основе решения @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")

Это намного безопаснее, потому что вы не можете забыть снова включить стандартный вывод, что особенно важно при обработке исключений.

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

4 голосов
/ 06 декабря 2011

Нет, нет, тем более что большинство PyGame написано на C.

Но если эта функция вызывает print, то это ошибка PyGame, и вы должны просто сообщить об этом.

3 голосов
/ 09 сентября 2017

Как предположил Александр Чжен, использовать менеджер контекста было бы безопаснее, чем вызывать пару функций, изменяющих состояние.

Однако вам не нужно переопределять менеджер контекста - он уже находится в стандартной библиотеке. Вы можете перенаправить stdout (объект файла, который используется print) с помощью 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.")
2 голосов
/ 02 октября 2018

Если вы хотите заблокировать вызовы печати, выполненные определенной функцией, есть более подходящее решение с использованием декораторов.Определите следующий декоратор:

# 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()
2 голосов
/ 06 декабря 2011

У меня была такая же проблема, и я не пришел к другому решению, кроме как перенаправить вывод программы (я точно не знаю, происходит ли рассылка спама на stdout или stderr) на /dev/null нирвану.

Действительно, это открытый исходный код, но я не был настолько увлечен, чтобы погрузиться в pygame источники - и процесс сборки - чтобы как-то остановить спам отладки.

РЕДАКТИРОВАТЬ:

Модуль pygame.joystick имеет вызовы printf во всех функциях, которые возвращают фактические значения в Python:

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

К сожалению, вам необходимо закомментировать их и перекомпилировать все это. Возможно, предоставленный setup.py сделает это проще, чем я думал. Вы можете попробовать это ...

1 голос
/ 05 июля 2017

Модуль, который я использовал, напечатан на stderr. Таким образом, решение в этом случае будет:

sys.stdout = open(os.devnull, 'w')
1 голос
/ 06 декабря 2011

Совершенно другой подход будет перенаправление в командной строке.Если вы работаете в Windows, это означает пакетный скрипт.В Linux, Bash.

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

Если вы не имеете дело с несколькими процессами, это должно работать.Для пользователей Windows это могут быть ярлыки, которые вы создаете (меню Пуск / Рабочий стол).

0 голосов
/ 17 июля 2019

Основываясь на решении @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) репутации для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...