Windows use the terminal to run the .bat file to open the project to customize the console color

Old rules, don’t talk nonsense, just go to the code:
.py file

import time

import inspect
import logging
import platform


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

        # 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_WHITE = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED

        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 >= 40):  # fatal/critical
            # color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY
            color = BACKGROUND_RED | FOREGROUND_WHITE | BACKGROUND_INTENSITY | FOREGROUND_INTENSITY
            # elif(levelno>=40): # error
        #    color = FOREGROUND_RED | FOREGROUND_INTENSITY
        elif (levelno >= 30):  # warn
            color = BACKGROUND_YELLOW | FOREGROUND_BLUE | BACKGROUND_INTENSITY | FOREGROUND_INTENSITY

        elif (levelno >= 20):  # info
            color = FOREGROUND_GREEN
        elif (levelno >= 10):  # debug
            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):
    # These are the sequences need to get colored ouput
    # RESET_SEQ = "\033[0m"
    # COLOR_SEQ = "\033[1;%dm"
    # BOLD_SEQ = "\033[1m"

    FG_BLACK = "\u001b[30m"
    FG_RED = "\u001b[31m"
    FG_GREEN = "\u001b[32m"
    FG_YELLOW = "\u001b[33m"
    FG_BLUE = "\u001b[34m"
    FG_MAGENTA = "\u001b[35m"
    FG_CYAN = "\u001b[36m"
    FG_WHITE = "\u001b[37m"

    FG_BLACK_B = "\u001b[30m;1m"
    FG_RED_B = "\u001b[31m;1m"
    FG_GREEN_B = "\u001b[32m;1m"
    FG_YELLOW_B = "\u001b[33m;1m"
    FG_BLUE_B = "\u001b[34m;1m"
    FG_MAGENTA_B = "\u001b[35m;1m"
    FG_CYAN_B = "\u001b[36m;1m"
    FG_WHITE_B = "\u001b[37m;1m"

    FG_ANY = "\u001b[38;5;{}m"

    RESET = "\u001b[0m"
    BOLD = "\u001b[1m"

    BG_BLACK = "\u001b[40m"
    BG_RED = "\u001b[41m"
    BG_GREEN = "\u001b[42m"
    BG_YELLOW = "\u001b[43m"
    BG_BLUE = "\u001b[44m"
    BG_MAGENTA = "\u001b[45m"
    BG_CYAN = "\u001b[46m"
    BG_WHITE = "\u001b[47m"

    BG_ANY = "\u001b[48;5;{}m"

    # red    \x1b[31m
    # yellow \x1b[33m
    # blue   \u001b[34m
    # black  \u001b[30m

    # reset  \x1b[0m

    # add methods we need to the class
    def new(*args):
        levelno = args[1].levelno
        if (levelno >= 40):  # critical/fatal
            fg = FG_WHITE + BOLD
            bg = BG_RED
        # elif(levelno>=40):#error
        #    fg = FG_RED
        #    bg = None
        elif (levelno >= 30):  # warn
            fg = FG_BLUE + BOLD
            bg = BG_YELLOW
        elif (levelno >= 20):  # info
            fg = FG_BLACK
            bg = None
        elif (levelno >= 10):  # debug
            fg = FG_MAGENTA
            bg = None
        else:
            fg = FG_MAGENTA
            bg = None

        # args[1].msg = fg + args[1].msg +  '\x1b[0m'  # normal
        if fg is None and bg is None:
            args[1].msg = args[1].msg + RESET
        else:
            args[1].msg = fg + ('' if bg is None else bg) + args[1].msg + RESET  # normal

        return fn(*args)

    return new


def addColorConsoleSupport():
    if platform.system() == 'Windows':
        def isDebugMode():
            for frame in inspect.stack():
                # print(frame)
                if frame[1].endswith("pydevd.py"):
                    return True

            return False

        def isDebugMode2():
            # does not work, all are True
            if __debug__:
                return True
            return False
            # Windows does not support ANSI escapes and we are using API calls to set the console color

        #
        # on windows, if we use eclipse IDE + Ansi Console, we switch to ansi emitter, windows console , we switch to windows emitter
        if isDebugMode():
            logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit)
        else:
            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)


from logging import getLogger, FileHandler, Formatter, StreamHandler, \
    raiseExceptions, INFO, DEBUG, WARN, ERROR
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
import os
import sys

loggers = {
    
    }


# The background is set with 40 plus the number of the color, and the foreground with 30

def prepareLogging(name, logDir):
    global loggers
    if loggers.get(name):
        return loggers.get(name)
    else:
        logger = getLogger(name)
        # dir must exist, so create dir
        # FIXME: if no absolute path is assigned, logs directory will be in the same directory with  mainPictureServer.py - use the relative path first.
        # any better solution?
        if not os.path.exists(logDir):
            os.makedirs(logDir)

        # TimedRotatingFileHandler : when - (s)econd|(m)inute|(h)our|(d)ay|w0-26(0-monday)|midnight
        hdlr = TimedRotatingFileHandler(logDir + "/" + name + ".txt", when="d", interval=1, backupCount=30)
        # hdlr = RotatingFileHandler(logDir+"/"+name+".txt", maxBytes=1024<<10, backupCount=30)
        # formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        formatter = Formatter(
            '%(thread)-6.6s %(asctime)s.%(msecs)02.2d %(filename)-12.12s_%(lineno)03d %(levelname)-3.3s] %(message)s',
            '%m-%d %H:%M:%S')

        hdlr.setFormatter(formatter)
        logger.addHandler(hdlr)

        ch = StreamHandler()
        ch.setLevel(INFO)
        formatter = Formatter(
            '%(thread)-4.4s %(asctime)s.%(msecs)02.2d %(filename)-12.12s_%(lineno)03d] %(levelname)-2.2s] %(message)s',
            '%M:%S')
        ch.setFormatter(formatter)
        # logger.propagate = False #without this, message will be duplicated
        logger.addHandler(ch)

        loggers[name] = logger

        logger.setLevel(INFO)
        return logger


if hasattr(sys, 'frozen'):  # support for py2exe
    _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:])
elif __file__[-4:].lower() in ['.pyc', '.pyo']:
    _srcfile = __file__[:-4] + '.py'
else:
    _srcfile = __file__
_srcfile = os.path.normcase(_srcfile)

if hasattr(sys, '_getframe'):
    currentframe = lambda: sys._getframe(3)
else:  # pragma: no cover
    def currentframe():
        """Return the frame object for the caller's stack frame."""
        try:
            raise Exception
        except Exception:
            return sys.exc_info()[2].tb_frame.f_back


class MyLogger(object):
    # as the caller will be MyLogger, so need copy logger implement for info(), warning, error()

    def __init__(self, logger):
        self.logger = logger

    def debug(self, msg, *args, **kwargs):
        if self.logger.isEnabledFor(DEBUG):
            self._log(DEBUG, msg, args, **kwargs)

    def info(self, msg, *args, **kwargs):
        if self.logger.isEnabledFor(INFO):
            self._log(INFO, msg, args, **kwargs)

    def warn(self, msg, *args, **kwargs):
        if self.logger.isEnabledFor(WARN):
            self._log(WARN, msg, args, **kwargs)

    def error(self, msg, *args, **kwargs):
        if self.logger.isEnabledFor(ERROR):
            self._log(ERROR, msg, args, **kwargs)

    def _log(self, level, msg, args, exc_info=None, extra=None):
        """
        Low-level logging routine which creates a LogRecord and then calls
        all the handlers of this logger to handle the record.
        """
        # Add wrapping functionality here.
        if _srcfile:
            # IronPython doesn't track Python frames, so findCaller throws an
            # exception on some versions of IronPython. We trap it here so that
            # IronPython can use logging.
            try:
                fn, lno, func = self.findCaller()
            except ValueError:
                fn, lno, func = "(unknown file)", 0, "(unknown function)"
        else:
            fn, lno, func = "(unknown file)", 0, "(unknown function)"
        if exc_info:
            if not isinstance(exc_info, tuple):
                exc_info = sys.exc_info()
        record = self.logger.makeRecord(
            self.logger.name, level, fn, lno, msg, args, exc_info, func, extra)
        self.logger.handle(record)

    def findCaller(self):
        """
        Find the stack frame of the caller so that we can note the source
        file name, line number and function name.
        """
        f = currentframe()
        # On some versions of IronPython, currentframe() returns None if
        # IronPython isn't run with -X:Frames.
        if f is not None:
            f = f.f_back
        rv = "(unknown file)", 0, "(unknown function)"
        while hasattr(f, "f_code"):
            co = f.f_code
            filename = os.path.normcase(co.co_filename)
            if filename == _srcfile:
                f = f.f_back
                continue
            rv = (co.co_filename, f.f_lineno, co.co_name)
            break
        return rv

    def log(self, level, msg, *args, **kwargs):
        """
        Log 'msg % args' with the integer severity 'level'.

        To pass exception information, use the keyword argument exc_info with
        a true value, e.g.

        logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
        """
        if not isinstance(level, int):
            if raiseExceptions:
                raise TypeError("level must be an integer")
            else:
                return
        if self.logger.isEnabledFor(level):
            self._log(level, msg, args, **kwargs)

    def _prefix(self, elevId):
        if str(elevId) == '1':
            prefix = ''
        else:
            prefix = ' ' * 30
        return prefix

    def infoE(self, elevId, msg, *args, **kwargs):
        self.info("{}{}".format(self._prefix(elevId), msg), *args, **kwargs)

    def warnE(self, elevId, msg, *args, **kwargs):
        self.warn("{}{}".format(self._prefix(elevId), msg), *args, **kwargs)

    def errorE(self, elevId, msg, *args, **kwargs):
        self.error("{}{}".format(self._prefix(elevId), msg), *args, **kwargs)

    def print0(self, msg, *args, **kwargs):
        method_name = sys._getframe(1).f_code.co_name
        line_no = sys._getframe(1).f_lineno
        _m = "{}_{}:{}{}".format(method_name, line_no, "", msg)
        print(_m)
        self.debug(_m, *args, **kwargs)

    def printE(self, elevId, msg, *args, **kwargs):
        p = self._prefix(elevId)
        method_name = sys._getframe(1).f_code.co_name
        line_no = sys._getframe(1).f_lineno
        _m = "{}_{}:{}{}".format(method_name, line_no, p, msg)
        print(p + msg)
        self.debug(p + msg, *args, **kwargs)


def ttColor(logger):
    while 1:
        time.sleep(2)
        logger.info('---------background color------------')


if __name__ == '__main__':
    addColorConsoleSupport()
    logger = MyLogger(prepareLogging("color", './logs'))
    ttColor(logger)

.bat script file

title=smartHomeService-V1.0
color 0F
rem @echo off
cd %~dp0
set cd=%~dp0
set PY_HOME=D:\Install\Python3.5.3
set PYTHONPATH=%cd%src;D:\Install\Env\ElevDispatching\Lib\site-packages;
set PATH=%PATH%;%PY_HOME%;%PY_HOME%/Scripts;%cd%/Scripts
@echo on
cd src/com/test
python ttcolor.py

note: Switch the script file to the .py file directory and start running.

Running effect:
Insert picture description here
done!

Guess you like

Origin blog.csdn.net/qq_43030934/article/details/107341442