Est-il possible d'empêcher une fonction d'appeler print
?
J'utilise le module pygame.joystick
pour un jeu sur lequel je travaille.
J'ai créé un objet pygame.joystick.Joystick
et, dans la boucle réelle du jeu, appelez 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 aussi print
, ce qui ralentit considérablement le jeu.
Puis-je bloquer cet appel en print
?
Python vous permet d'écraser la sortie standard (stdout) avec n'importe quel objet fichier. Cela devrait fonctionner sur plusieurs plates-formes 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 souhaitez pas que cette fonction soit imprimée, appelez blockPrint()
devant elle et enablePrint()
si vous souhaitez qu'elle continue. Si vous souhaitez désactiver all printing, commencez à bloquer en haut du fichier.
Sur la base de la solution @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
Ensuite, vous pouvez l'utiliser comme ceci:
with HiddenPrints():
print("This will not be printed")
print("This will be printed as before")
Ceci est beaucoup plus sûr car vous ne pouvez pas oublier de réactiver stdout, ce qui est particulièrement critique lors du traitement des exceptions.
# 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.
Si vous avez oublié la clause finally
, aucun de vos appels print
n'imprimera plus rien. En utilisant la déclaration with
, cela ne peut pas arriver.
Il n'est pas prudent d'utiliser sys.stdout = None
, car quelqu'un pourrait appeler des méthodes telles que sys.stdout.write ().
Non, il n'y en a pas, surtout que la majorité de PyGame est écrite en C.
Mais si cette fonction appelle print, il s’agit d’un bogue PyGame et vous devez simplement le signaler.
J'ai eu le même problème, et je ne suis pas venu à une autre solution mais pour rediriger la sortie du programme (je ne sais pas exactement si le spamming se produit sur stdout ou stderr) à /dev/null
nirvana.
En effet, il est open source, mais je n’étais pas assez passionné pour plonger dans les sources pygame
- et le processus de construction - afin d’arrêter le spam de débogage.
MODIFIER :
Le module pygame.joystick
a des appels à printf
dans toutes les fonctions qui renvoient les valeurs réelles à Python:
printf("SDL_JoystickGetButton value:%d:\n", value);
Malheureusement, vous devez les commenter et recompiler le tout. Peut-être que le setup.py
fourni rendrait cela plus facile que je ne le pensais. Tu pourrais essayer ça ...
Si vous souhaitez bloquer les appels d'impression effectués par une fonction particulière, il existe une solution plus simple utilisant 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
Ensuite, placez simplement @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()
Le module que j'ai utilisé imprimé à stderr
. La solution dans ce cas serait donc:
sys.stdout = open(os.devnull, 'w')
Comme @Alexander Chzhen l'a suggéré, il serait plus sûr d'utiliser un gestionnaire de contexte que d'appeler deux fonctions qui changent d'état.
Cependant, vous n'avez pas besoin de réimplémenter le gestionnaire de contexte - il est déjà dans la bibliothèque standard. Vous pouvez rediriger stdout
(l'objet fichier utilisé par print
) avec contextlib.redirect_stdout
, ainsi que stderr
avec contextlib.redirect_stderr
.
import os
import contextlib
with open(os.devnull, "w") as f, contextlib.redirect_stdout(f):
print("This won't be printed.")
Une approche complètement différente consisterait à rediriger en ligne de commande. Si vous êtes sous Windows, cela signifie un script batch. Sous Linux, bash.
/full/path/to/my/game/game.py > /dev/null
C:\Full\Path\To\My\Game.exe > nul
À moins que vous ne traitiez avec plusieurs processus, ceci devrait fonctionne. Pour les utilisateurs Windows, il peut s’agir des raccourcis que vous créez (menu Démarrer/Bureau).