2009-04-02 11 views
8

Estoy ejecutando Python 2.4 en un motor de juego y quiero poder apagar todas las copias si es necesario. Por ejemplo, me gustaría tener las impresiones activadas para una compilación de depuración y luego desactivarlas para una versión de lanzamiento. También es imprescindible que sea lo más transparente posible.¿Cuál es la mejor manera de alternar impresiones de pitón?

Mi solución para esto en el código C del motor es tener la función printf dentro de una macro vararg, y definir eso para no hacer nada en una compilación de lanzamiento.

Ésta es mi solución actual:

DebugPrints = True 
def PRINT (*args): 
    global DebugPrints 
    if DebugPrints: 
     string = "" 
     for arg in args: 
      string += " " + str(arg) 
     print string 

Se hace fácil para cambiar impresiones, pero no es posible una mejor manera de formato a la cadena. Mi problema principal es que esto realmente agrega muchas más llamadas de función al programa.

Me pregunto si hay algo que pueda hacer sobre cómo funciona la palabra clave de impresión.

+0

en lugar del bucle, se puede usar 'impresión "" .join (args)' –

+0

Uy, que debería haber sido "impresión" .join (mapa (str, args)) –

+0

Aún utilizando 2.4? –

Respuesta

12

sí, puedes asignar sys.stdout a lo que quieras. Crear una pequeña clase con un método que no hace nada write:

class DevNull(object): 
    def write(self, arg): 
     pass 

import sys  
sys.stdout = DevNull() 
print "this goes to nirvana!" 

Con la misma técnica también puede tener sus impresiones conectado a un archivo mediante el establecimiento de sys.stdout a un objeto fichero abierto.

+0

No olvide hacer una copia de seguridad del sys.stdout si desea volver a habilitarlo más tarde. _stdout = sys.stdout; sys.stdout = DevNull() –

+0

Con módulos como "logging", este método parece un poco ridículo. –

+0

'ridículo' es un poco exagerado pero entiendo tu punto. Debería haber llamado a la pregunta 'la forma más fácil de alternar impresiones', tal vez? –

3

No utilice impresión, pero cree una clase de consola que maneje toda la impresión. Simplemente realice llamadas a la consola y la consola puede decidir si realmente las imprime. Una clase de consola también es útil para cosas como mensajes de error y advertencia o redirigir a dónde va la salida.

+0

+1: usando el registro o enrolle el suyo. Pero no uses print. –

+0

Sí, vale la pena mirar un módulo de registro existente. Dependiendo del alcance del proyecto, una pequeña clase podría ser suficiente. –

+0

El módulo de registro integrado es bastante bueno. –

8

El logging module es la "mejor" .. aunque muy a menudo sólo tiene que utilizar algo tan simple como ..

class MyLogger: 
    def _displayMessage(self, message, level = None): 
     # This can be modified easily 
     if level is not None: 
      print "[%s] %s" % (level, message 
     else: 
      print "[default] %s" % (message) 

    def debug(self, message): 
     self._displayMessage(message, level = "debug") 
    def info(self, message): 
     self._displayMessage(message, level = "info") 

log = MyLogger() 
log.info("test") 
10

sé una respuesta ya ha sido marcada como correcta, pero Python tiene un indicador de depuración que proporciona una solución más limpia. Se utiliza de esta manera:

if __debug__: 
    print "whoa" 

Si se invoca con Python o -O -OO (como lo haría normalmente para una versión de lanzamiento), __debug__ está puesto en False. Lo que es aún mejor es que __debug__ es un caso especial para el intérprete; en realidad quitará ese código cuando escriba los archivos pyc/pyo, haciendo que el código resultante sea más pequeño/más rápido. Tenga en cuenta que no puede asignar valores a __debug__, por lo que está completamente basado en esos argumentos de línea de comandos.

+0

+1: Eso es útil saber, incluso si es un poco más esfuerzo implementar –

+0

Es una pena que el indicador de depuración esté activado cuando simplemente se usa python ./thescript.py (en lugar de usar el indicador de depuración -d) – dbr

0

he respondido a esta pregunta en un different post pero fue la pregunta estuvo marcado por duplicado:

todos modos, esto es lo que yo haría:

from __future__ import print_function 
DebugPrints = 0 

def print(*args, **kwargs): 
    if DebugPrints: 
     return __builtins__.print(*args, **kwargs) 

print('foo') # doesn't get printed 
DebugPrints = 1 
print('bar') # gets printed 

lamentablemente no se puede mantener la sintaxis de impresión AP2 print 'foo'

+0

Funciona muy bien. Pero, ¿cómo sabe la función de impresión sobre 'enable_print', si no es global y no se ha pasado como argumento? – Pyderman

1

Si realmente desea alternar la impresión:

>>> import sys 
>>> import os 
>>> print 'foo' 
foo 
>>> origstdout = sys.stdout 
>>> sys.stdout = open(os.devnull, 'w') 
>>> print 'foo' 
>>> sys.stdout = origstdout 
>>> print 'foo' 
foo 

Sin embargo, le recomiendo que solo use print para el código desechable. Use logging para aplicaciones reales como la pregunta original describe.Permite una escala móvil de verbosidad, por lo que solo puede tener el registro importante o un registro más detallado de detalles generalmente menos importantes.

>>> import logging 
>>> logging.basicConfig(level=logging.DEBUG) 
>>> logging.debug('foo') 
DEBUG:root:foo 

Por ejemplo, el uso podría ser colocar registros de depuración en todo el código. Luego, para silenciarlos, cambiar su nivel a un nivel superior, uno de INFO, WARN o WARNING, ERROR o CRITICAL o FATAL

>>> logging.root.setLevel(logging.INFO) 
>>> logging.debug('foo') 
>>> 

En un script que querrá acaba de establecer esto en el basicConfig como esto :

import logging 
logging.basicConfig(level=logging.INFO) 

logging.debug('foo') # this will be silent 

uso más sofisticado de la tala se puede encontrar in the docs.


Cuestiones relacionadas