2010-05-23 5 views
7

I ont les fonctions suivantes pour colorisation mes messages d'écran:impression à STDOUT et le fichier journal tout en supprimant les codes couleurs ANSI

def error(string): 
    return '\033[31;1m' + string + '\033[0m' 

def standout(string): 
    return '\033[34;1m' + string + '\033[0m' 

Je les utilise comme suit:

print error('There was a problem with the program') 
print "This is normal " + standout("and this stands out") 

Je veux connecter le sortie vers un fichier (en plus de STDOUT) SANS les codes de couleurs ANSI, sans avoir à ajouter une seconde ligne "logging" à chaque instruction print. La raison est que si vous simplement python program.py > out alors le fichier out aura les codes de couleur ANSI, ce qui semble terrible si vous ouvrez dans un éditeur de texte en clair.

Un conseil?

Répondre

9

La fonction sys.stdout.isatty pourrait être en mesure d'aider:

from sys import stdout 

def error(string, is_tty=stdout.isatty()): 
    return ('\033[31;1m' + string + '\033[0m') if is_tty else string 

def standout(string, is_tty=stdout.isatty()): 
    return ('\033[34;1m' + string + '\033[0m') if is_tty else string 

C'est en fait l'un des rares utilisations que je peux penser à utiliser un argument par défaut qui n'est pas réglé sur None parce que les arguments par défaut sont évalués à la compilation temps en Python plutôt qu'en C++ ...

Aussi le comportement peut être explicitement remplacé si vous en avez vraiment besoin, bien que cela ne vous laisse pas manipuler stdout lui-même quand il est redirigé. Y at-il une raison pour laquelle vous n'utilisez pas le module logging (peut-être que vous ne le saviez pas)?

+0

Excellente réponse - cela peut être exactement ce que j'ai besoin. J'utilise actuellement le module de journalisation, mais je souhaite que l'utilisateur ait la possibilité de rediriger la sortie et d'obtenir un fichier lisible par l'utilisateur. Le journal lui-même est créé par le module de journalisation (et avec votre approche, je vais probablement obtenir ce que je veux). – Escualo

+0

Je viens de tester votre approche et cela fonctionne exactement comme prévu. Merci beaucoup! – Escualo

5

Si vous souhaitez imprimer sur le terminal et sur un fichier journal, je vous suggère d'utiliser le module de journalisation. Vous pouvez même définir une mise en forme personnalisée, de sorte que la connexion au fichier peut purger les codes terminaux:

import optparse 
import logging 

def error(string): 
    return '\033[31;1m' + string + '\033[0m' 

def standout(string): 
    return '\033[34;1m' + string + '\033[0m' 

def plain(string): 
    return string.replace('\033[34;1m','').replace('\033[31;1m','').replace('\033[0m','') 

if __name__=='__main__': 
    logging.basicConfig(level=logging.DEBUG, 
         format='%(message)s', 
         filemode='w') 
    logger=logging.getLogger(__name__)  
    def parse_options():  
     usage = 'usage: %prog [Options]' 
     parser = optparse.OptionParser() 
     parser.add_option('-l', '--logfile', dest='logfile', 
          help='use log file') 
     opt,args = parser.parse_args() 
     return opt,args 
    opt,args=parse_options() 
    if opt.logfile: 
     class MyFormatter(logging.Formatter): 
      def format(self,record): 
       return plain(record.msg) 
     fh = logging.FileHandler(opt.logfile) 
     fh.setLevel(logging.INFO) 
     formatter = MyFormatter('%(message)s') 
     fh.setFormatter(formatter) 
     logging.getLogger('').addHandler(fh) 

    logger.info(error('There was a problem with the program')) 
    logger.info("This is normal " + standout("and this stands out")) 

test.py imprime uniquement au terminal.

test.py -l test.out imprime à la fois le terminal et le fichier test.out.

Dans tous les cas, le texte sur le terminal a des codes de couleur alors que l'enregistrement n'en a pas.

1

La réponse de unubtu ci-dessous est grande, mais je pense que MyFormatter a besoin d'une modification mineure pour appliquer le formatage dans la méthode format()

class MyFormatter(logging.Formatter): 
     def format(self,record): 
      msg = super(MyFormatter, self).format(record) 
      return plain(msg) 
Questions connexes