La impresión en stdout y el archivo de registro mientras se quita los códigos de color ANSI

StackOverflow https://stackoverflow.com/questions/2893650

Pregunta

Tengo las siguientes funciones para colorear mis mensajes de pantalla:

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

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

Las uso de la siguiente manera:

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

Quiero registrar la salida a un archivo (además de STDOUT) sin los códigos de color ANSI, es de esperar sin tener que añadir un segundo "registro" de línea a cada declaración print.

La razón es que si simplemente python program.py > out entonces el out archivo tendrá los códigos de color ANSI, que se ven terribles si se abre en un editor de texto plano.

Cualquier consejo?

¿Fue útil?

Solución

La función sys.stdout.isatty podría ser capaz de ayudar:

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

Eso es en realidad uno de los pocos usos que se me ocurre para usar un argumento predeterminado que no se ajusta a None porque los argumentos por defecto son evaluados en tiempo de compilación en Python en lugar de en tiempo de ejecución como en C ++ ...

También el comportamiento puede ser anulado de forma explícita si realmente necesita, aunque eso no le permiten manipular la salida estándar en sí cuando es redirigido. ¿Hay alguna razón por la que no está utilizando el módulo logging (tal vez usted no sabía sobre él)?

Otros consejos

Si desea imprimir en tanto el terminal como un archivo de registro, entonces yo sugeriría usar el módulo de registro. Incluso puede definir un formateador personalizado, por lo que el registro en el fichero puede purgar los códigos de terminal:

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"))

sólo se imprime test.py al terminal.

impresiones test.py -l test.out tanto al terminal y al test.out archivo.

En todos los casos, el texto al terminal tiene códigos de color, mientras que el registro no tiene ninguna.

La respuesta de unubtu a continuación es grande, pero creo que myFormatter necesita una pequeña modificación para hacer cumplir el formato en el método format ()

class MyFormatter(logging.Formatter):
        def format(self,record):
            msg = super(MyFormatter, self).format(record)
            return plain(msg)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top