2009-04-02 17 views
8

Sto eseguendo Python 2.4 in un motore di gioco e voglio essere in grado di spegnere tutte le stampe, se necessario. Per esempio mi piacerebbe avere le stampe su per una build di debug, e quindi disattivato per una build di rilascio. È anche imperativo che sia il più trasparente possibile.Qual è il modo migliore per attivare le stampe Python?

La mia soluzione a questo nel codice C del motore è la funzione printf all'interno di una macro vararg e la definizione di non fare nulla in una versione di rilascio.

Questa è la mia soluzione attuale:

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

Lo rende facile per alternare stampe, ma c'è forse un modo migliore per formattare la stringa. Il mio problema principale è che questo è in realtà l'aggiunta di molte più chiamate di funzione al programma.

Mi chiedo se c'è qualcosa che puoi fare su come funziona la parola chiave di stampa?

+0

invece del ciclo for, è possibile utilizzare 'stampa "" .join (args)' –

+0

oops, che avrebbe dovuto essere di stampa "" .join (mappa (str, args)) –

+0

Sempre con 2.4? –

risposta

12

sì, è possibile assegnare sys.stdout a quello che vuoi. Creare un po 'di classe con un metodo write che non fa nulla:

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

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

Con la stessa tecnica si può anche avere le stampe registrati in un file impostando sys.stdout a un oggetto file aperto.

+0

Non dimenticare di eseguire il backup di sys.stdout se si desidera riattivarlo in seguito. _stdout = sys.stdout; sys.stdout = DevNull() –

+0

Con moduli come "logging", questo metodo sembra un po 'ridicolo. –

+0

"ridicolo" è un po 'esagerato ma capisco il tuo punto. Avrei dovuto chiamare la domanda "Modo più semplice per attivare le stampe", forse? –

3

Non utilizzare la stampa, ma creare una classe di console che gestisca tutta la stampa. È sufficiente effettuare chiamate alla console e la console può decidere se stamparle effettivamente o meno. Una classe di console è utile anche per cose come messaggi di errore e di avvertimento o per reindirizzare dove va l'output.

+0

+1: utilizzando la registrazione o il rollover. Ma non usare la stampa. –

+0

Sì, vale la pena esaminare un modulo di registrazione esistente. A seconda dello scopo del progetto, una piccola classe potrebbe essere sufficiente. –

+0

Il modulo di registrazione incorporato è abbastanza buono. –

8

Il logging module è il modo "migliore" .. anche se ho molto spesso basta usare qualcosa di semplice come ..

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

so una risposta è già stato contrassegnato come corretta, ma Python ha una bandiera di debug che fornisce una soluzione più pulita. Si utilizza in questo modo:

if __debug__: 
    print "whoa" 

Se si richiama Python con -O o -OO (come si farebbe normalmente per un build di rilascio), __debug__ è impostato su False. Quello che è ancora meglio è che __debug__ è un caso speciale per l'interprete; in realtà verrà rimosso quel codice quando scrive i file pyc/pyo, rendendo il codice risultante più piccolo/più veloce. Si noti che non è possibile assegnare valori a __debug__, quindi è interamente basato su tali argomenti della riga di comando.

+0

+1: È utile sapere, anche se è un po 'più difficile implementare –

+0

È un peccato che il flag di debug sia attivo quando si fa semplicemente python ./thescript.py (invece di usare il flag -d debug) – dbr

0

Ho risposto a questa domanda su una different post ma è stata la questione è stato caratterizzato duplicato:

ogni caso, ecco cosa farei:

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 

purtroppo non è possibile mantenere la sintassi di stampa PY2 print 'foo'

+0

Funziona bene. Ma come fa la funzione di stampa a sapere 'enable_print', se non è globale e non è stata passata come argomento? – Pyderman

1

Se davvero si vuole attivare o disattivare la stampa:

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

Tuttavia, si consiglia di utilizzare solo print per il codice throwaway. Usa logging per applicazioni reali come la domanda originale descrive.Permette una scala scorrevole di verbosità, quindi puoi avere solo la registrazione importante, o una registrazione più dettagliata di dettagli solitamente meno importanti.

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

Ad esempio, l'utilizzo potrebbe consistere nel mettere i registri di debug nel codice. Poi per farli tacere, modificare il livello ad un livello superiore, uno dei INFO, WARN o WARNING, ERROR, o CRITICAL o FATAL

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

In uno script si vorrà impostare proprio questo nel basicConfig come questo :

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

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

utilizzo più sofisticato di registrazione può essere trovato in the docs.


Problemi correlati