2011-12-05 23 views
22

¿Hay alguna manera de evitar que una función llame a imprimir? ¿O, en términos más generales, una forma de llamar a una función y hacer que ejecute todo su código a excepción de una llamada de función particular?Suprimir llamadas para imprimir (python)

Mi caso concreto: Estoy usando el módulo pygame.joystick para un juego en el que estoy trabajando.

Creé un objeto pygame.joystick.Joystick y en el bucle real del juego llamo a su función de miembro get_button para comprobar la entrada del usuario. La función hace todo lo que necesito que haga, pero el problema es que también llama al print, lo que ralentiza considerablemente el juego. ¿Algún consejo?

¡Gracias y espero que mi pregunta no fuera tan confusa!

Respuesta

5

No, no lo hay, sobre todo la mayoría de PyGame está escrito en C.

Pero si esta función se llama a la impresión, entonces es PyGame error, y que sólo debe informar de ello.

2

He tenido el mismo problema, y ​​no he encontrado otra solución que redirigir el resultado del programa (no sé exactamente si el correo no deseado se produce en stdout o stderr) a /dev/null nirvana.

De hecho, es de código abierto, pero no era lo suficientemente apasionado como para sumergirme en las fuentes pygame y el proceso de compilación para detener de alguna manera el spam de depuración.

EDIT:

El pygame.joystick module tiene llamadas a printf en todas las funciones que devuelven los valores reales a Python:

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

desgracia que tendría que comentar estos y recompilar todo el asunto. Tal vez el proporcionado setup.py haría esto más fácil de lo que pensaba. Puede probar esto ...

29

Python le permite sobrescribir la salida estándar (stdout) con cualquier objeto de archivo. Esto debería funcionar multiplataforma y escribir en el dispositivo nulo.

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 no desea que una función para imprimir, llame blockPrint() ante sí, y enablePrint() cuando se desea que continúe. Si desea deshabilitar la impresión , comience a bloquear en la parte superior del archivo.

+0

Esto parece haber bloqueado permanentemente la impresión para mí. enablePrint no lo restaura –

1

Un enfoque completamente diferente estaría redirigiendo a la línea de comandos. Si estás en Windows, esto significa un script por lotes. En Linux, bash.

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

A menos que usted está tratando con múltiples procesos, esto debe trabajo. Para los usuarios de Windows, estos podrían ser los accesos directos que está creando (menú de inicio/escritorio).

0

El módulo que utilicé se imprimió en stderr.Así que la solución en este caso sería:

sys.stdout = open(os.devnull, 'w') 
13

basado en la solución @FakeRainBrigand que estoy sugiriendo una solución más segura:

import os, sys 

class HiddenPrints: 
    def __enter__(self): 
     self._original_stdout = sys.stdout 
     sys.stdout = None 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     sys.stdout = self._original_stdout 

A continuación, se puede utilizar de esta manera:

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

print("This will be printed as before") 

Esto es mucho más seguro porque no puede olvidarse de volver a habilitar stdout, que es especialmente crítico cuando se manejan excepciones.

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 se le olvidó la finally cláusula, ninguna de sus llamadas print imprimiría nada más. Usando la declaración with, eso no puede suceder.

Según lo observado por @ WellDone2094, es posible asignar sys.stdout = None. Lo que hace que el código sea más claro. Es written que sys.stdout debería haber un FileObject, pero hay uno más note:

Bajo algunas condiciones stdin, stdout y stderr, así como los originales valores stdin, stdout y stderr puede ser ninguno Por lo general, es el caso de las aplicaciones de Windows GUI que no están conectadas a una consola y Las aplicaciones de Python se iniciaron con pythonw.

+2

¡Muy buena solución! Acabo de escribir lo mismo y luego encontré que ya respondiste de esa manera: D Voy a agregar un poco de información sobre por qué esta es una mejor manera de hacerlo. – iFreilicht

+0

Pregunta de Noobie aquí: ¿Sería importante cerrar() devnull después de salir de la clase? – Wadsworth

+0

@Wadsworth, no sé la respuesta. Supongo que las propiedades de Devnull no requieren que se cierre correctamente. Pero los rumores dicen que siempre debe cerrar los manejadores abiertos para liberar recursos. CPython, como sé, debería cerrar devnull hasta llegar al recolector de basura. –

0

Redirigir stdout (el objeto archivo que print utiliza) también se puede lograr con contextlib.redirect_stdout. Además, puede redirigir 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.") 
Cuestiones relacionadas