turtle rellenar programar programacion pintar hacer fractales figuras estrella dibujar con como circulo python logging colors

programar - rellenar turtle python



¿Cómo puedo colorear la salida de registro de Python? (24)

Hace algún tiempo, vi una aplicación Mono con salida de color, probablemente debido a su sistema de registro (porque todos los mensajes estaban estandarizados).

Ahora, Python tiene el módulo de logging , que le permite especificar muchas opciones para personalizar la salida. Entonces, estoy imaginando que algo similar sería posible con Python, pero no puedo descubrir cómo hacer esto en cualquier lugar.

¿Hay alguna manera de hacer que el módulo de logging Python se logging en color?

Lo que quiero (por ejemplo) errores en rojo, mensajes de depuración en azul o amarillo, etc.

Por supuesto, esto probablemente requeriría un terminal compatible (la mayoría de los terminales modernos son); pero podría retroceder a la salida de logging original si el color no es compatible.

¿Alguna idea de cómo puedo obtener una salida de color con el módulo de registro?


Actualicé el ejemplo de las etiquetas de soporte de airmind para el primer plano y el fondo. Simplemente use las variables de color $ BLACK - $ WHITE en la cadena del formateador de registro. Para establecer el fondo solo use $ BG-BLACK - $ BG-WHITE.

import logging BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) COLORS = { ''WARNING'' : YELLOW, ''INFO'' : WHITE, ''DEBUG'' : BLUE, ''CRITICAL'' : YELLOW, ''ERROR'' : RED, ''RED'' : RED, ''GREEN'' : GREEN, ''YELLOW'' : YELLOW, ''BLUE'' : BLUE, ''MAGENTA'' : MAGENTA, ''CYAN'' : CYAN, ''WHITE'' : WHITE, } RESET_SEQ = "/033[0m" COLOR_SEQ = "/033[1;%dm" BOLD_SEQ = "/033[1m" class ColorFormatter(logging.Formatter): def __init__(self, *args, **kwargs): # can''t do super(...) here because Formatter is an old school class logging.Formatter.__init__(self, *args, **kwargs) def format(self, record): levelname = record.levelname color = COLOR_SEQ % (30 + COLORS[levelname]) message = logging.Formatter.format(self, record) message = message.replace("$RESET", RESET_SEQ)/ .replace("$BOLD", BOLD_SEQ)/ .replace("$COLOR", color) for k,v in COLORS.items(): message = message.replace("$" + k, COLOR_SEQ % (v+30))/ .replace("$BG" + k, COLOR_SEQ % (v+40))/ .replace("$BG-" + k, COLOR_SEQ % (v+40)) return message + RESET_SEQ logging.ColorFormatter = ColorFormatter

Así que ahora puedes simplemente hacer lo siguiente en tu archivo de configuración:

[formatter_colorFormatter] class=logging.ColorFormatter format= $COLOR%(levelname)s $RESET %(asctime)s $BOLD$COLOR%(name)s$RESET %(message)s



Aquí está mi solución:

2017-09-29 00:32:23,434 - main - DEBUG - app has started 2017-09-29 00:32:23,434 - main - INFO - Logging to ''app.log'' in the script dir 2017-09-29 00:32:23,435 - main - WARNING - This is my last warning, take heed 2017-09-29 00:32:23,435 - main - ERROR - This is an error 2017-09-29 00:32:23,435 - main - CRITICAL - He''s dead, Jim 2017-09-29 00:32:23,435 - main.sub_module - ERROR - Hello from the sub module


Aquí hay una solución que debería funcionar en cualquier plataforma. Si no solo me lo dice y lo actualizo.

Cómo funciona: en la plataforma que admite ANSI escapes los está utilizando (no Windows) y en Windows usa llamadas API para cambiar los colores de la consola.

La secuencia de comandos piratea el método logging.StreamHandler.emit de la biblioteca estándar y le agrega un contenedor.

TestColorer.py

# Usage: add Colorer.py near you script and import it. import logging import Colorer logging.warn("a warning") logging.error("some error") logging.info("some info")

Colorer.py

#!/usr/bin/env python # encoding: utf-8 import logging # now we patch Python code to add color support to logging.StreamHandler def add_coloring_to_emit_windows(fn): # add methods we need to the class def _out_handle(self): import ctypes return ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE) out_handle = property(_out_handle) def _set_color(self, code): import ctypes # Constants from the Windows API self.STD_OUTPUT_HANDLE = -11 hdl = ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE) ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, code) setattr(logging.StreamHandler, ''_set_color'', _set_color) def new(*args): FOREGROUND_BLUE = 0x0001 # text color contains blue. FOREGROUND_GREEN = 0x0002 # text color contains green. FOREGROUND_RED = 0x0004 # text color contains red. FOREGROUND_INTENSITY = 0x0008 # text color is intensified. FOREGROUND_WHITE = FOREGROUND_BLUE|FOREGROUND_GREEN |FOREGROUND_RED # winbase.h STD_INPUT_HANDLE = -10 STD_OUTPUT_HANDLE = -11 STD_ERROR_HANDLE = -12 # wincon.h FOREGROUND_BLACK = 0x0000 FOREGROUND_BLUE = 0x0001 FOREGROUND_GREEN = 0x0002 FOREGROUND_CYAN = 0x0003 FOREGROUND_RED = 0x0004 FOREGROUND_MAGENTA = 0x0005 FOREGROUND_YELLOW = 0x0006 FOREGROUND_GREY = 0x0007 FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified. BACKGROUND_BLACK = 0x0000 BACKGROUND_BLUE = 0x0010 BACKGROUND_GREEN = 0x0020 BACKGROUND_CYAN = 0x0030 BACKGROUND_RED = 0x0040 BACKGROUND_MAGENTA = 0x0050 BACKGROUND_YELLOW = 0x0060 BACKGROUND_GREY = 0x0070 BACKGROUND_INTENSITY = 0x0080 # background color is intensified. levelno = args[1].levelno if(levelno>=50): color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY elif(levelno>=40): color = FOREGROUND_RED | FOREGROUND_INTENSITY elif(levelno>=30): color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY elif(levelno>=20): color = FOREGROUND_GREEN elif(levelno>=10): color = FOREGROUND_MAGENTA else: color = FOREGROUND_WHITE args[0]._set_color(color) ret = fn(*args) args[0]._set_color( FOREGROUND_WHITE ) #print "after" return ret return new def add_coloring_to_emit_ansi(fn): # add methods we need to the class def new(*args): levelno = args[1].levelno if(levelno>=50): color = ''/x1b[31m'' # red elif(levelno>=40): color = ''/x1b[31m'' # red elif(levelno>=30): color = ''/x1b[33m'' # yellow elif(levelno>=20): color = ''/x1b[32m'' # green elif(levelno>=10): color = ''/x1b[35m'' # pink else: color = ''/x1b[0m'' # normal args[1].msg = color + args[1].msg + ''/x1b[0m'' # normal #print "after" return fn(*args) return new import platform if platform.system()==''Windows'': # Windows does not support ANSI escapes and we are using API calls to set the console color logging.StreamHandler.emit = add_coloring_to_emit_windows(logging.StreamHandler.emit) else: # all non-Windows platforms are supporting ANSI escapes so we use them logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit) #log = logging.getLogger() #log.addFilter(log_filter()) #//hdlr = logging.StreamHandler() #//hdlr.setFormatter(formatter())


Bueno, supongo que también podría agregar mi variación del registrador de colores.

Esto no es nada sofisticado, pero es muy simple de usar y no cambia el objeto de registro, por lo que evita el registro de las secuencias de escape ANSI en un archivo de registro si se usa un controlador de archivos. No afecta el formato del mensaje de registro.

Si ya está utilizando el formateador del módulo de registro , todo lo que tiene que hacer para obtener nombres de nivel de color es reemplazar el manejador de abogados Formatter por el ColoredFormatter. Si está registrando una aplicación completa, solo necesita hacer esto para el registrador de nivel superior.

colored_log.py

class ColouredFormatter(logging.Formatter): RESET = ''/x1B[0m'' RED = ''/x1B[31m'' YELLOW = ''/x1B[33m'' BRGREEN = ''/x1B[01;32m'' # grey in solarized for terminals def format(self, record, colour=False): message = super().format(record) if not colour: return message level_no = record.levelno if level_no >= logging.CRITICAL: colour = self.RED elif level_no >= logging.ERROR: colour = self.RED elif level_no >= logging.WARNING: colour = self.YELLOW elif level_no >= logging.INFO: colour = self.RESET elif level_no >= logging.DEBUG: colour = self.BRGREEN else: colour = self.RESET message = colour + message + self.RESET return message class ColouredHandler(logging.StreamHandler): def __init__(self, stream=sys.stdout): super().__init__(stream) def format(self, record, colour=False): if not isinstance(self.formatter, ColouredFormatter): self.formatter = ColouredFormatter() return self.formatter.format(record, colour) def emit(self, record): stream = self.stream try: msg = self.format(record, stream.isatty()) stream.write(msg) stream.write(self.terminator) self.flush() except Exception: self.handleError(record) h = ColouredHandler() h.formatter = ColouredFormatter(''{asctime} {levelname:8} {message}'', ''%Y-%m-%d %H:%M:%S'', ''{'') logging.basicConfig(level=logging.DEBUG, handlers=[h])

Ejemplo de uso

app.py

#!/usr/bin/env python from copy import copy from logging import Formatter MAPPING = { ''DEBUG'' : 37, # white ''INFO'' : 36, # cyan ''WARNING'' : 33, # yellow ''ERROR'' : 31, # red ''CRITICAL'': 41, # white on red bg } PREFIX = ''/033['' SUFFIX = ''/033[0m'' class ColoredFormatter(Formatter): def __init__(self, patern): Formatter.__init__(self, patern) def format(self, record): colored_record = copy(record) levelname = colored_record.levelname seq = MAPPING.get(levelname, 37) # default white colored_levelname = (''{0}{1}m{2}{3}'') / .format(PREFIX, seq, levelname, SUFFIX) colored_record.levelname = colored_levelname return Formatter.format(self, colored_record)

sub_module.py

#!/usr/bin/env python import logging from colored_log import ColoredFormatter # Create top level logger log = logging.getLogger("main") # Add console handler using our custom ColoredFormatter ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) cf = ColoredFormatter("[%(name)s][%(levelname)s] %(message)s (%(filename)s:%(lineno)d)") ch.setFormatter(cf) log.addHandler(ch) # Add file handler fh = logging.FileHandler(''app.log'') fh.setLevel(logging.DEBUG) ff = logging.Formatter(''%(asctime)s - %(name)s - %(levelname)s - %(message)s'') fh.setFormatter(ff) log.addHandler(fh) # Set log level log.setLevel(logging.DEBUG) # Log some stuff log.debug("app has started") log.info("Logging to ''app.log'' in the script dir") log.warning("This is my last warning, take heed") log.error("This is an error") log.critical("He''s dead, Jim") # Import a sub-module import sub_module

Resultados

Salida de terminal

contenido de app.log

#!/usr/bin/env python import logging log = logging.getLogger(''main.sub_module'') log.debug("Hello from the sub module")

Por supuesto, puede obtener todo lo que quiera con el formato del terminal y las salidas de archivos de registro. Sólo el nivel de registro será coloreado.

Espero que alguien lo encuentre útil y no sea mucho más de lo mismo. :)

Los archivos de ejemplo de Python se pueden descargar de este GitHub Gist: https://gist.github.com/KurtJacobson/48e750701acec40c7161b5a2f79e6bfd


El problema con el que tuve problemas fue configurar correctamente el formateador:

class ColouredFormatter(logging.Formatter): def __init__(self, msg): logging.Formatter.__init__(self, msg) self._init_colour = _get_colour() def close(self): # restore the colour information to what it was _set_colour(self._init_colour) def format(self, record): # Add your own colourer based on the other examples _set_colour( LOG_LEVEL_COLOUR[record.levelno] ) return logging.Formatter.format(self, record) def init(): # Set up the formatter. Needs to be first thing done. rootLogger = logging.getLogger() hdlr = logging.StreamHandler() fmt = ColouredFormatter(''%(message)s'') hdlr.setFormatter(fmt) rootLogger.addHandler(hdlr)

Y luego usar:

import coloured_log import logging coloured_log.init() logging.info("info") logging.debug("debug") coloured_log.close() # restore colours


Hace años escribí un controlador de flujo de color para mi propio uso. Luego encontré esta página y encontré una colección de fragmentos de código que las personas están copiando / pegando :-(. Mi controlador de secuencias actualmente solo funciona en UNIX (Linux, Mac OS X) pero la ventaja es que está disponible en PyPI (y GitHub ) y es muy sencillo de usar. También tiene un modo de sintaxis Vim :-). En el futuro podría extenderlo para que funcione en Windows.

Para instalar el paquete:

$ pip install coloredlogs

Para confirmar que funciona:

$ coloredlogs --demo

Para comenzar con su propio código:

$ python > import coloredlogs, logging > coloredlogs.install() > logging.info("It works!") 2014-07-30 21:21:26 peter-macbook root[7471] INFO It works!

El formato de registro predeterminado que se muestra en el ejemplo anterior contiene la fecha, la hora, el nombre de host, el nombre del registrador, el PID, el nivel de registro y el mensaje de registro. Esto es lo que parece en la práctica:


Hay toneladas de respuestas. Pero ninguno habla de decoradores. Así que aquí está la mía.

Porque es mucho más simple.

No es necesario importar nada, ni escribir ninguna subclase:

#!/usr/bin/env python # -*- coding: utf-8 -*- import logging NO_COLOR = "/33[m" RED, GREEN, ORANGE, BLUE, PURPLE, LBLUE, GREY = / map("/33[%dm".__mod__, range(31, 38)) logging.basicConfig(format="%(message)s", level=logging.DEBUG) logger = logging.getLogger(__name__) # the decorator to apply on the logger methods info, warn, ... def add_color(logger_method, color): def wrapper(message, *args, **kwargs): return logger_method( # the coloring is applied here. color+message+NO_COLOR, *args, **kwargs ) return wrapper for level, color in zip(( "info", "warn", "error", "debug"), ( GREEN, ORANGE, RED, BLUE )): setattr(logger, level, add_color(getattr(logger, level), color)) # this is displayed in red. logger.error("Launching %s." % __file__)

Esto establece los errores en rojo, los mensajes de depuración en azul, y así sucesivamente. Como se pregunta en la pregunta.

Incluso podríamos adaptar la envoltura para tomar un argumento de color para establecer dinámicamente el color del mensaje usando logger.debug("message", color=GREY)

EDIT: Así que aquí está el decorador adaptado para establecer colores en tiempo de ejecución:

def add_color(logger_method, _color): def wrapper(message, *args, **kwargs): color = kwargs.pop("color", _color) if isinstance(color, int): color = "/33[%dm" % color return logger_method( # the coloring is applied here. color+message+NO_COLOR, *args, **kwargs ) return wrapper # blah blah, apply the decorator... # this is displayed in red. logger.error("Launching %s." % __file__) # this is displayed in blue logger.error("Launching %s." % __file__, color=34) # and this, in grey logger.error("Launching %s." % __file__, color=GREY)



Modifiqué el ejemplo original proporcionado por Sorin y subclasificé StreamHandler a ColorizedConsoleHandler.

La desventaja de su solución es que modifica el mensaje, y como eso está modificando el mensaje de registro real, cualquier otro manejador recibirá el mensaje modificado también.

Esto resultó en archivos de registro con códigos de colores en nuestro caso porque usamos múltiples registradores.

La siguiente clase solo funciona en plataformas compatibles con ansi, pero debería ser trivial agregarle los códigos de colores de Windows.

import copy import logging class ColoredConsoleHandler(logging.StreamHandler): def emit(self, record): # Need to make a actual copy of the record # to prevent altering the message for other loggers myrecord = copy.copy(record) levelno = myrecord.levelno if(levelno >= 50): # CRITICAL / FATAL color = ''/x1b[31m'' # red elif(levelno >= 40): # ERROR color = ''/x1b[31m'' # red elif(levelno >= 30): # WARNING color = ''/x1b[33m'' # yellow elif(levelno >= 20): # INFO color = ''/x1b[32m'' # green elif(levelno >= 10): # DEBUG color = ''/x1b[35m'' # pink else: # NOTSET and anything else color = ''/x1b[0m'' # normal myrecord.msg = color + str(myrecord.msg) + ''/x1b[0m'' # normal logging.StreamHandler.emit(self, myrecord)


Otro remix menor del enfoque de Airmind que mantiene todo en una clase:

class ColorFormatter(logging.Formatter): FORMAT = ("[$BOLD%(name)-20s$RESET][%(levelname)-18s] " "%(message)s " "($BOLD%(filename)s$RESET:%(lineno)d)") BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) RESET_SEQ = "/033[0m" COLOR_SEQ = "/033[1;%dm" BOLD_SEQ = "/033[1m" COLORS = { ''WARNING'': YELLOW, ''INFO'': WHITE, ''DEBUG'': BLUE, ''CRITICAL'': YELLOW, ''ERROR'': RED } def formatter_msg(self, msg, use_color = True): if use_color: msg = msg.replace("$RESET", self.RESET_SEQ).replace("$BOLD", self.BOLD_SEQ) else: msg = msg.replace("$RESET", "").replace("$BOLD", "") return msg def __init__(self, use_color=True): msg = self.formatter_msg(self.FORMAT, use_color) logging.Formatter.__init__(self, msg) self.use_color = use_color def format(self, record): levelname = record.levelname if self.use_color and levelname in self.COLORS: fore_color = 30 + self.COLORS[levelname] levelname_color = self.COLOR_SEQ % fore_color + levelname + self.RESET_SEQ record.levelname = levelname_color return logging.Formatter.format(self, record)

Para usar adjuntar el formateador a un controlador, algo como:

handler.setFormatter(ColorFormatter()) logger.addHandler(handler)


Puede importar el módulo de registro de color y usar su ColoredFormatter para colorear los mensajes de registro.

Ejemplo

Boilerplate para el módulo principal:

import logging import os import sys try: import colorlog except ImportError: pass def setup_logging(): root = logging.getLogger() root.setLevel(logging.DEBUG) format = ''%(asctime)s - %(levelname)-8s - %(message)s'' date_format = ''%Y-%m-%d %H:%M:%S'' if ''colorlog'' in sys.modules and os.isatty(2): cformat = ''%(log_color)s'' + format f = colorlog.ColoredFormatter(cformat, date_format, log_colors = { ''DEBUG'' : ''reset'', ''INFO'' : ''reset'', ''WARNING'' : ''bold_yellow'', ''ERROR'': ''bold_red'', ''CRITICAL'': ''bold_red'' }) else: f = logging.Formatter(format, date_format) ch = logging.StreamHandler() ch.setFormatter(f) root.addHandler(ch) setup_logging() log = logging.getLogger(__name__)

El código solo habilita los colores en los mensajes de registro, si el módulo de registro de color está instalado y si la salida realmente va a un terminal. Esto evita que las secuencias de escape se escriban en un archivo cuando se redirige la salida del registro.

Además, se configura un esquema de color personalizado que es más adecuado para terminales con fondo oscuro.

Algunos ejemplos de llamadas de registro:

log.debug (''Hello Debug'') log.info (''Hello Info'') log.warn (''Hello Warn'') log.error (''Hello Error'') log.critical(''Hello Critical'')

Salida:


Solución rápida y sucia para niveles de registro predefinidos y sin definir una nueva clase.

logging.addLevelName( logging.WARNING, "/033[1;31m%s/033[1;0m" % logging.getLevelName(logging.WARNING)) logging.addLevelName( logging.ERROR, "/033[1;41m%s/033[1;0m" % logging.getLevelName(logging.ERROR))


Una herramienta simple pero muy flexible para colorear CUALQUIER texto terminal es '' colout ''.

pip install colout myprocess | colout REGEX_WITH_GROUPS color1,color2...

Donde cualquier texto en la salida de ''myprocess'' que coincida con el grupo 1 de la expresión regular se coloreará con color1, grupo 2 con color2, etc.

Por ejemplo:

tail -f /var/log/mylogfile | colout ''^(/w+ /d+ [/d:]+)|(/w+/.py:/d+ .+/(/)): (.+)$'' white,black,cyan bold,bold,normal

es decir, el primer grupo de expresiones regulares (parens) coincide con la fecha inicial en el archivo de registro, el segundo grupo coincide con un nombre de archivo de python, número de línea y nombre de la función, y el tercer grupo coincide con el mensaje de registro que viene después de eso. También utilizo una secuencia paralela de "negrita / normal", así como la secuencia de colores. Esto se ve como

Tenga en cuenta que las líneas o partes de líneas que no coinciden con mi regex todavía tienen eco, así que esto no es como ''grep --color'' - nada se filtra fuera de la salida.

Obviamente, esto es lo suficientemente flexible como para que pueda usarlo con cualquier proceso, no solo siguiendo los archivos de registro. Por lo general, solo levanto un nuevo regex sobre la marcha cada vez que quiero colorear algo. Por esta razón, prefiero colout a cualquier herramienta personalizada para colorear archivos de log, porque solo necesito aprender una herramienta, independientemente de lo que esté coloreando: registro, salida de prueba, resaltado de sintaxis, fragmentos de código en el terminal, etc.

También evita el hecho de volcar códigos ANSI en el archivo de registro, lo cual, en mi humilde opinión, es una mala idea, porque romperá cosas como grepping para patrones en el archivo de registro a menos que siempre recuerde que coincida con los códigos ANSI en su regex grep.


Ya sabía acerca de los escapes de color, los usé en mi mensaje de bash hace un tiempo. Gracias de cualquier manera.
Lo que quería era integrarlo con el módulo de registro, lo que finalmente hice después de un par de intentos y errores.
Esto es lo que termino con:

BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) #The background is set with 40 plus the number of the color, and the foreground with 30 #These are the sequences need to get colored ouput RESET_SEQ = "/033[0m" COLOR_SEQ = "/033[1;%dm" BOLD_SEQ = "/033[1m" def formatter_message(message, use_color = True): if use_color: message = message.replace("$RESET", RESET_SEQ).replace("$BOLD", BOLD_SEQ) else: message = message.replace("$RESET", "").replace("$BOLD", "") return message COLORS = { ''WARNING'': YELLOW, ''INFO'': WHITE, ''DEBUG'': BLUE, ''CRITICAL'': YELLOW, ''ERROR'': RED } class ColoredFormatter(logging.Formatter): def __init__(self, msg, use_color = True): logging.Formatter.__init__(self, msg) self.use_color = use_color def format(self, record): levelname = record.levelname if self.use_color and levelname in COLORS: levelname_color = COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ record.levelname = levelname_color return logging.Formatter.format(self, record)

Y para usarlo, crea tu propio Logger:

# Custom logger class with multiple destinations class ColoredLogger(logging.Logger): FORMAT = "[$BOLD%(name)-20s$RESET][%(levelname)-18s] %(message)s ($BOLD%(filename)s$RESET:%(lineno)d)" COLOR_FORMAT = formatter_message(FORMAT, True) def __init__(self, name): logging.Logger.__init__(self, name, logging.DEBUG) color_formatter = ColoredFormatter(self.COLOR_FORMAT) console = logging.StreamHandler() console.setFormatter(color_formatter) self.addHandler(console) return logging.setLoggerClass(ColoredLogger)

Por si alguien más lo necesita.

Tenga cuidado si está utilizando más de un registrador o controlador: ColoredFormatter está cambiando el objeto de registro, que se pasa a otros controladores o se propaga a otros registradores. Si ha configurado los registradores de archivos, etc., es probable que no quiera tener los colores en los archivos de registro. Para evitar eso, probablemente sea mejor crear una copia del record con copy.copy() antes de manipular el atributo levelname, o restablecer el levelname al valor anterior, antes de devolver la cadena con formato (crédito a Michael en los comentarios).


Actualización : como esta es una picazón que he querido rascar durante tanto tiempo, seguí adelante y escribí una biblioteca para personas perezosas como yo, que solo quieren formas simples de hacer las cosas: zenlog

Colorlog es excelente para esto. Está disponible en PyPI (y, por lo tanto, se puede instalar a través de pip install colorlog ) y se mantiene activamente .

Aquí hay un fragmento rápido para copiar y pegar para configurar el registro e imprimir mensajes de registro de aspecto decente:

import logging LOG_LEVEL = logging.DEBUG LOGFORMAT = " %(log_color)s%(levelname)-8s%(reset)s | %(log_color)s%(message)s%(reset)s" from colorlog import ColoredFormatter logging.root.setLevel(LOG_LEVEL) formatter = ColoredFormatter(LOGFORMAT) stream = logging.StreamHandler() stream.setLevel(LOG_LEVEL) stream.setFormatter(formatter) log = logging.getLogger(''pythonConfig'') log.setLevel(LOG_LEVEL) log.addHandler(stream) log.debug("A quirky message only developers care about") log.info("Curious users might want to know this") log.warn("Something is wrong and any user should be informed") log.error("Serious stuff, this is red for a reason") log.critical("OH NO everything is on fire")

Salida:


Este es un Enum que contiene los códigos de color:

class TerminalColour: """ Terminal colour formatting codes """ # https://.com/questions/287871/print-in-terminal-with-colors MAGENTA = ''/033[95m'' BLUE = ''/033[94m'' GREEN = ''/033[92m'' YELLOW = ''/033[93m'' RED = ''/033[91m'' GREY = ''/033[0m'' # normal WHITE = ''/033[1m'' # bright white UNDERLINE = ''/033[4m''

Esto se puede aplicar a los nombres de cada nivel de registro. Ten en cuenta que este es un hack monstruoso.

logging.addLevelName(logging.INFO, "{}{}{}".format(TerminalColour.WHITE, logging.getLevelName(logging.INFO), TerminalColour.GREY)) logging.addLevelName(logging.WARNING, "{}{}{}".format(TerminalColour.YELLOW, logging.getLevelName(logging.WARNING), TerminalColour.GREY)) logging.addLevelName(logging.ERROR, "{}{}{}".format(TerminalColour.RED, logging.getLevelName(logging.ERROR), TerminalColour.GREY)) logging.addLevelName(logging.CRITICAL, "{}{}{}".format(TerminalColour.MAGENTA, logging.getLevelName(logging.CRITICAL), .GREY))

Tenga en cuenta que el formateador de su registro debe incluir el nombre del nivel de registro

%(levelname)

por ejemplo:

LOGGING = { ... ''verbose'': { ''format'': ''%(asctime)s %(levelname)s %(name)s:%(lineno)s %(module)s %(process)d %(thread)d %(message)s'' }, ''simple'': { ''format'': ''[%(asctime)s] %(levelname)s %(name)s %(message)s'' },


Una solución más, con los colores de ZetaSyanthis:

def config_log(log_level): def set_color(level, code): level_fmt = "/033[1;" + str(code) + "m%s/033[1;0m" logging.addLevelName( level, level_fmt % logging.getLevelName(level) ) std_stream = sys.stdout isatty = getattr(std_stream, ''isatty'', None) if isatty and isatty(): levels = [logging.DEBUG, logging.CRITICAL, logging.WARNING, logging.ERROR] for idx, level in enumerate(levels): set_color(level, 30 + idx ) set_color(logging.DEBUG, 0) logging.basicConfig(stream=std_stream, level=log_level)

Llámalo una vez desde tu __main__función. Tengo algo como esto allí:

options, arguments = p.parse_args() log_level = logging.DEBUG if options.verbose else logging.WARNING config_log(log_level)

También verifica que la salida sea una consola, de lo contrario no se utilizan colores.



Si bien las otras soluciones parecen estar bien, tienen algunos problemas. Algunos colorean las líneas completas, lo que algunas veces no se desea, y otros omiten cualquier configuración que pueda tener todos juntos. La solución a continuación no afecta nada más que el mensaje en sí.

Código

class ColoredFormatter(logging.Formatter): def format(self, record): if record.levelno == logging.WARNING: record.msg = ''/033[93m%s/033[0m'' % record.msg elif record.levelno == logging.ERROR: record.msg = ''/033[91m%s/033[0m'' % record.msg return logging.Formatter.format(self, record)

Ejemplo

logger = logging.getLogger(''mylogger'') handler = logging.StreamHandler() log_format = ''[%(asctime)s]:%(levelname)-7s:%(message)s'' time_format = ''%H:%M:%S'' formatter = ColoredFormatter(log_format, datefmt=time_format) handler.setFormatter(formatter) logger.addHandler(handler) logger.warn(''this should be yellow'') logger.error(''this should be red'')

Salida

[17:01:36]:WARNING:this should be yellow [17:01:37]:ERROR :this should be red

Como puede ver, todo lo demás aún se imprime y permanece en su color inicial. Si desea cambiar algo más que el mensaje, simplemente puede pasar los códigos de color log_formaten el ejemplo.


Tengo dos presentaciones para agregar, una de las cuales colorea solo el mensaje (ColoredFormatter) y una de las que colorea la línea completa (ColorizingStreamHandler). Estos también incluyen más códigos de color ANSI que las soluciones anteriores.

Parte del contenido se ha obtenido (con modificaciones) de: La publicación anterior y http://plumberjack.blogspot.com/2010/12/colorizing-logging-output-in-terminals.html .

Colorea solo el mensaje:

class ColoredFormatter(logging.Formatter): """Special custom formatter for colorizing log messages!""" BLACK = ''/033[0;30m'' RED = ''/033[0;31m'' GREEN = ''/033[0;32m'' BROWN = ''/033[0;33m'' BLUE = ''/033[0;34m'' PURPLE = ''/033[0;35m'' CYAN = ''/033[0;36m'' GREY = ''/033[0;37m'' DARK_GREY = ''/033[1;30m'' LIGHT_RED = ''/033[1;31m'' LIGHT_GREEN = ''/033[1;32m'' YELLOW = ''/033[1;33m'' LIGHT_BLUE = ''/033[1;34m'' LIGHT_PURPLE = ''/033[1;35m'' LIGHT_CYAN = ''/033[1;36m'' WHITE = ''/033[1;37m'' RESET = "/033[0m" def __init__(self, *args, **kwargs): self._colors = {logging.DEBUG: self.DARK_GREY, logging.INFO: self.RESET, logging.WARNING: self.BROWN, logging.ERROR: self.RED, logging.CRITICAL: self.LIGHT_RED} super(ColoredFormatter, self).__init__(*args, **kwargs) def format(self, record): """Applies the color formats""" record.msg = self._colors[record.levelno] + record.msg + self.RESET return logging.Formatter.format(self, record) def setLevelColor(self, logging_level, escaped_ansi_code): self._colors[logging_level] = escaped_ansi_code

Colorea toda la línea:

class ColorizingStreamHandler(logging.StreamHandler): BLACK = ''/033[0;30m'' RED = ''/033[0;31m'' GREEN = ''/033[0;32m'' BROWN = ''/033[0;33m'' BLUE = ''/033[0;34m'' PURPLE = ''/033[0;35m'' CYAN = ''/033[0;36m'' GREY = ''/033[0;37m'' DARK_GREY = ''/033[1;30m'' LIGHT_RED = ''/033[1;31m'' LIGHT_GREEN = ''/033[1;32m'' YELLOW = ''/033[1;33m'' LIGHT_BLUE = ''/033[1;34m'' LIGHT_PURPLE = ''/033[1;35m'' LIGHT_CYAN = ''/033[1;36m'' WHITE = ''/033[1;37m'' RESET = "/033[0m" def __init__(self, *args, **kwargs): self._colors = {logging.DEBUG: self.DARK_GREY, logging.INFO: self.RESET, logging.WARNING: self.BROWN, logging.ERROR: self.RED, logging.CRITICAL: self.LIGHT_RED} super(ColorizingStreamHandler, self).__init__(*args, **kwargs) @property def is_tty(self): isatty = getattr(self.stream, ''isatty'', None) return isatty and isatty() def emit(self, record): try: message = self.format(record) stream = self.stream if not self.is_tty: stream.write(message) else: message = self._colors[record.levelno] + message + self.RESET stream.write(message) stream.write(getattr(self, ''terminator'', ''/n'')) self.flush() except (KeyboardInterrupt, SystemExit): raise except: self.handleError(record) def setLevelColor(self, logging_level, escaped_ansi_code): self._colors[logging_level] = escaped_ansi_code


Utilice pyfancy .

Ejemplo:

print(pyfancy.RED + "Hello Red!" + pyfancy.END)


import logging logging.basicConfig(filename="f.log" filemode=''w'', level=logging.INFO, format = "%(logger_name)s %(color)s %(message)s %(endColor)s") class Logger(object): __GREEN = "/033[92m" __RED = ''/033[91m'' __ENDC = ''/033[0m'' def __init__(self, name): self.logger = logging.getLogger(name) self.extra={''logger_name'': name, ''endColor'': self.__ENDC, ''color'': self.__GREEN} def info(self, msg): self.extra[''color''] = self.__GREEN self.logger.info(msg, extra=self.extra) def error(self, msg): self.extra[''color''] = self.__RED self.logger.error(msg, extra=self.extra)

Uso

Logger("File Name").info("This shows green text")


import logging import sys colors = {''pink'': ''/033[95m'', ''blue'': ''/033[94m'', ''green'': ''/033[92m'', ''yellow'': ''/033[93m'', ''red'': ''/033[91m'', ''ENDC'': ''/033[0m'', ''bold'': ''/033[1m'', ''underline'': ''/033[4m''} logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) def str_color(color, data): return colors[color] + str(data) + colors[''ENDC''] params = {''param1'': id1, ''param2'': id2} logging.info(''/nParams:'' + str_color("blue", str(params)))`