544 Stimmen

Wie kann ich die Python-Logging-Ausgabe einfärben?

Vor einiger Zeit sah ich eine Mono-Anwendung mit farbiger Ausgabe, vermutlich aufgrund des Protokollsystems (da alle Meldungen standardisiert waren).

Jetzt hat Python die logging Modul, mit dem Sie eine Vielzahl von Optionen zur Anpassung der Ausgabe angeben können. Ich stelle mir vor, dass etwas Ähnliches auch mit Python möglich wäre, aber ich kann nirgendwo herausfinden, wie man das macht.

Gibt es eine Möglichkeit, die Python logging Modulausgabe in Farbe?

Ich möchte z. B. Fehler in rot, Fehlermeldungen in blau oder gelb usw.

Natürlich würde dies wahrscheinlich ein kompatibles Terminal erfordern (die meisten modernen Terminals sind kompatibel); aber ich könnte auf die ursprüngliche logging Ausgabe, wenn Farbe nicht unterstützt wird.

Haben Sie eine Idee, wie ich mit dem Logging-Modul eine farbige Ausgabe erhalten kann?

6voto

Mojtaba Hosseini Punkte 68078

Emoji

Sie können Farben für Text verwenden, wie andere in ihren Antworten erwähnt haben, um bunten Text mit einer Hintergrund- oder Vordergrundfarbe zu haben.

Aber Sie können Emojis stattdessen! Sie können zum Beispiel verwenden für Warnmeldungen und für Fehlermeldungen.

Oder verwenden Sie diese Notizbücher einfach als Farbe:

print(": error message")
print(": warning message")
print(": ok status message")
print(": action message")
print(": canceled status message")
print(": Or anything you like and want to recognize immediately by color")

Bonus:

Mit dieser Methode können Sie auch schnell Protokolle scannen und finden direkt im Quellcode .


Wie öffnet man den Emoji-Picker?

Mac OS : control + command + space

Windows : win + .

linux : control + . o control + ;

4voto

Serhii Khachko Punkte 49
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)))`

3voto

Scott Punkte 1615

Dies ist eine weitere Python3-Variante des Beispiels von airmind. Ich wollte einige spezielle Funktionen, die ich in den anderen Beispielen nicht gesehen habe

  • Farben für das Terminal verwenden, aber keine nicht druckbaren Zeichen in die Datei-Handler schreiben (ich habe dafür 2 Formatierer definiert)
  • Möglichkeit, die Farbe für eine bestimmte Protokollmeldung zu ändern
  • den Logger aus einer Datei konfigurieren (in diesem Fall yaml)

Anmerkungen: Ich habe colorama aber Sie könnten dies ändern, so dass es nicht erforderlich ist. Auch für meine Tests habe ich gerade Python-Datei ausgeführt, so dass meine Klasse in Modul ist __main__ Sie müssen Folgendes ändern (): __main__.ColoredFormatter auf das jeweilige Modul.

pip install colorama pyyaml

logging.yaml

---
version: 1
disable_existing_loggers: False
formatters:
  simple:
    format: "%(threadName)s - %(name)s - %(levelname)s - %(message)s"
  color:
    format: "%(threadName)s - %(name)s - %(levelname)s - %(message)s"
    (): __main__.ColoredFormatter
    use_color: true

handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: color
    stream: ext://sys.stdout

  info_file_handler:
    class: logging.handlers.RotatingFileHandler
    level: INFO
    formatter: simple
    filename: app.log
    maxBytes: 20971520 
    backupCount: 20
    encoding: utf8

  error_file_handler:
    class: logging.handlers.RotatingFileHandler
    level: ERROR
    formatter: simple
    filename: errors.log
    maxBytes: 10485760 
    backupCount: 20
    encoding: utf8

root:
  level: DEBUG
  handlers: [console, info_file_handler, error_file_handler]

main.py

import logging
import logging.config
import os
from logging import Logger

import colorama
import yaml
from colorama import Back, Fore, Style

COLORS = {
    "WARNING": Fore.YELLOW,
    "INFO": Fore.CYAN,
    "DEBUG": Fore.BLUE,
    "CRITICAL": Fore.YELLOW,
    "ERROR": Fore.RED,
}

class ColoredFormatter(logging.Formatter):
    def __init__(self, *, format, use_color):
        logging.Formatter.__init__(self, fmt=format)
        self.use_color = use_color

    def format(self, record):
        msg = super().format(record)
        if self.use_color:
            levelname = record.levelname
            if hasattr(record, "color"):
                return f"{record.color}{msg}{Style.RESET_ALL}"
            if levelname in COLORS:
                return f"{COLORS[levelname]}{msg}{Style.RESET_ALL}"
        return msg

with open("logging.yaml", "rt") as f:
    config = yaml.safe_load(f.read())
    logging.config.dictConfig(config)

logger: Logger = logging.getLogger(__name__)
logger.info("Test INFO", extra={"color": Back.RED})
logger.info("Test INFO", extra={"color": f"{Style.BRIGHT}{Back.RED}"})
logger.info("Test INFO")
logger.debug("Test DEBUG")
logger.warning("Test WARN")

Ausgabe:

output

2voto

veegee Punkte 349

Hier ist meine Lösung:

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

2voto

shakfu Punkte 21

Dies ist eine leichte Abwandlung von @Sergey Pleshakovs hervorragender Antwort, die Farbe nur auf die Ebenen anwendet und Folgendes verwendet basicConfig wie erwartet:

class CustomFormatter(logging.Formatter):

    white = "\x1b[97;20m"
    grey = "\x1b[38;20m"
    green = "\x1b[32;20m"
    cyan = "\x1b[36;20m"
    yellow = "\x1b[33;20m"
    red = "\x1b[31;20m"
    bold_red = "\x1b[31;1m"
    reset = "\x1b[0m"
    fmt = "%(asctime)s - {}%(levelname)-8s{} - %(name)s.%(funcName)s - %(message)s"

    FORMATS = {
        logging.DEBUG: fmt.format(grey, reset),
        logging.INFO: fmt.format(green, reset),
        logging.WARNING: fmt.format(yellow, reset),
        logging.ERROR: fmt.format(red, reset),
        logging.CRITICAL: fmt.format(bold_red, reset),
    }

    def format(self, record):
        log_fmt = self.FORMATS.get(record.levelno)
        formatter = logging.Formatter(log_fmt, datefmt="%H:%M:%S")
        return formatter.format(record)

handler = logging.StreamHandler()
handler.setFormatter(CustomFormatter())
logging.basicConfig(
    level=logging.DEBUG,
    handlers=[handler]
)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X