128 votes

Comment bloquer les appels à imprimer ?

Existe-t-il un moyen d'empêcher une fonction d'appeler print ?


J'utilise le pygame.joystick pour un jeu sur lequel je travaille.

J'ai créé un pygame.joystick.Joystick et, dans la boucle du jeu, appeler sa fonction membre get_button pour vérifier la saisie de l'utilisateur. La fonction fait tout ce dont j'ai besoin, mais le problème est qu'elle appelle également print ce qui ralentit considérablement le jeu.

Puis-je bloc cet appel à print ?

162voto

FakeRainBrigand Points 12463

Python vous permet d'écraser la sortie standard (stdout) avec n'importe quel objet fichier. Cela devrait fonctionner sur toutes les plateformes et écrire sur le périphérique null.

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"

Si vous ne voulez pas que cette fonction soit imprimée, appelez blockPrint() devant lui, et enablePrint() lorsque vous souhaitez qu'elle se poursuive. Si vous souhaitez désactiver tous l'impression, commencer le blocage au début du fichier.

138voto

Alexander Chzhen Points 1302

Utilisation with

Sur la base de la solution de @FakeRainBrigand, je propose une solution plus sûre :

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

Vous pouvez alors l'utiliser comme suit :

with HiddenPrints():
    print("This will not be printed")

print("This will be printed as before")

C'est beaucoup plus sûr car vous ne pouvez pas oublier de réactiver stdout, ce qui est particulièrement critique lors de la gestion des exceptions.

Sans with - Mauvaises pratiques

L'exemple suivant utilise les fonctions d'activation/désactivation des impressions qui ont été suggérées dans la réponse précédente.

Imaginez qu'il existe un code susceptible de soulever une exception. Nous devons utiliser finally afin d'activer les impressions dans tous les cas.

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.

Si vous avez oublié le finally aucune de vos print n'imprime plus rien.

Il est plus sûr d'utiliser le with qui garantit que les impressions seront réactivées.

Remarque : il n'est pas sûr d'utiliser sys.stdout = None car quelqu'un pourrait appeler des méthodes comme sys.stdout.write()

73voto

Comme l'a suggéré @Alexander Chzhen, l'utilisation d'un gestionnaire de contexte serait plus sûre que l'appel à une paire de fonctions de changement d'état.

Cependant, il n'est pas nécessaire de réimplémenter le gestionnaire de contexte : il se trouve déjà dans la bibliothèque standard. Vous pouvez rediriger stdout (l'objet fichier que print utilisations) avec contextlib.redirect_stdout et aussi stderr con contextlib.redirect_stderr .

import os
import contextlib

with open(os.devnull, "w") as f, contextlib.redirect_stdout(f):
    print("This won't be printed.")

17voto

Fowler Points 325

Si vous souhaitez bloquer les appels d'impression effectués par une fonction particulière, il existe une solution plus nette qui consiste à utiliser des décorateurs. Définissez le décorateur suivant :

# 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

Il suffit ensuite de placer @blockPrinting avant toute fonction. Par exemple :

# This will print
def helloWorld():
    print("Hello World!")
helloWorld()

# This will not print
@blockPrinting
def helloWorld2():
    print("Hello World!")
helloWorld2()

8voto

PascalIv Points 228

Si vous utilisez Jupyter Notebook ou Colab, utilisez ceci :

from IPython.utils import io

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X