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?

365voto

Sergey Pleshakov Punkte 6357

2022 Lösung, keine zusätzlichen Pakete erforderlich, Python 3

Definieren Sie eine Klasse

import logging

class CustomFormatter(logging.Formatter):

    grey = "\x1b[38;20m"
    yellow = "\x1b[33;20m"
    red = "\x1b[31;20m"
    bold_red = "\x1b[31;1m"
    reset = "\x1b[0m"
    format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)"

    FORMATS = {
        logging.DEBUG: grey + format + reset,
        logging.INFO: grey + format + reset,
        logging.WARNING: yellow + format + reset,
        logging.ERROR: red + format + reset,
        logging.CRITICAL: bold_red + format + reset
    }

    def format(self, record):
        log_fmt = self.FORMATS.get(record.levelno)
        formatter = logging.Formatter(log_fmt)
        return formatter.format(record)

Logger instanziieren

# create logger with 'spam_application'
logger = logging.getLogger("My_app")
logger.setLevel(logging.DEBUG)

# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

ch.setFormatter(CustomFormatter())

logger.addHandler(ch)

Und nutzen!

logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical message")

Ergebnis enter image description here

Das vollständige Farbschema enter image description here

Für Windows

Diese Lösung funktioniert auf Mac OS und IDE-Terminals. Die Windows-Eingabeaufforderung scheint standardmäßig keine Farben zu haben. Hier sind Anweisungen, wie man sie aktivieren kann, was ich nicht ausprobiert habe https://www.howtogeek.com/322432/how-to-customize-your-command-prompts-color-scheme-with-microsofts-colortool/

230voto

airmind Punkte 6561

Ich wusste bereits über die Farbe Escapes, ich habe sie in meinem Bash Prompt vor einer Weile verwendet. Trotzdem danke.
Was ich wollte, war die Integration mit dem Logging-Modul, was ich nach einigen Versuchen und Fehlern schließlich geschafft habe.
Das ist mein Ergebnis:

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)

Und um es zu benutzen, erstellen Sie Ihren eigenen 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)

Nur für den Fall, dass jemand anderes es braucht.

Seien Sie vorsichtig, wenn Sie mehr als einen Logger oder Handler verwenden: ColoredFormatter ist die Änderung des Datensatzobjekts, das an andere Handler weitergegeben oder an andere Logger propagiert wird. Wenn Sie Dateilogger usw. konfiguriert haben, möchten Sie wahrscheinlich nicht, dass die Farben in den Protokolldateien angezeigt werden. Um das zu vermeiden, ist es wahrscheinlich am besten, einfach eine Kopie von record con copy.copy() bevor das Attribut levelname manipuliert wird, oder um den levelname auf den vorherigen Wert zurückzusetzen, bevor die formatierte Zeichenkette zurückgegeben wird (Dank an Michael in den Kommentaren).

211voto

xolox Punkte 4588

Vor Jahren schrieb ich einen farbigen Stream-Handler für meinen eigenen Gebrauch. Dann stieß ich auf diese Seite und fand eine Sammlung von Codeschnipseln, die von anderen kopiert und eingefügt wurden :-(. Mein Stream-Handler funktioniert derzeit nur unter UNIX (Linux, Mac OS X), aber der Vorteil ist, dass er verfügbar auf PyPI (und GitHub ) und es ist kinderleicht zu bedienen. Es hat auch einen Vim-Syntaxmodus :-). In Zukunft werde ich es vielleicht erweitern, damit es unter Windows funktioniert.

So installieren Sie das Paket:

$ pip install coloredlogs

Um zu bestätigen, dass es funktioniert:

$ coloredlogs --demo

So beginnen Sie mit Ihrem eigenen Code:

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

Das im obigen Beispiel gezeigte Standardprotokollformat enthält das Datum, die Uhrzeit, den Hostnamen, den Namen des Loggers, die PID, die Protokollstufe und die Protokollmeldung. So sieht es in der Praxis aus:

Screenshot of coloredlogs output

HINWEIS: Bei Verwendung von Git Bash mit MinTTY

Git Bash unter Windows hat einige dokumentierte Macken: Winpty und Git Bash

Für ANSI-Escape-Codes und für das Umschreiben von Zeichen und Animationen im Stil von ncurses müssen Sie den Befehlen das Wort winpty .

$ winpty coloredlogs --demo
$ winpty python your_colored_logs_script.py

116voto

rlafuente Punkte 1764

Update : Da dies ein Bedürfnis ist, das ich schon so lange stillen wollte, habe ich eine Bibliothek für faule Leute wie mich geschrieben, die nur einfache Möglichkeiten wollen, Dinge zu tun: zenlog

Colorlog ist hierfür hervorragend geeignet. Es ist verfügbar auf PyPI (und damit installierbar durch pip install colorlog ) und ist aktiv gepflegt .

Hier ist ein schnell kopierbares Snippet, um die Protokollierung einzurichten und anständig aussehende Protokollnachrichten zu drucken:

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

Ausgabe:

Colorlog output

96voto

ABC Punkte 799

Schnelle und schmutzige Lösung für vordefinierte Protokollstufen und ohne Definition einer neuen Klasse.

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

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