这是一个完整且精心打包的解决方案,基于Waterboy的答案和其他来源。它支持向控制台和日志文件记录日志,允许设置不同的日志级别,并提供了彩色输出和易于配置的功能(也可作为Gist使用):
import os
import sys
import logging
class LogFormatter(logging.Formatter):
COLOR_CODES = {
logging.CRITICAL: "\033[1;35m",
logging.ERROR: "\033[1;31m",
logging.WARNING: "\033[1;33m",
logging.INFO: "\033[0;37m",
logging.DEBUG: "\033[1;30m"
}
RESET_CODE = "\033[0m"
def __init__(self, color, *args, **kwargs):
super(LogFormatter, self).__init__(*args, **kwargs)
self.color = color
def format(self, record, *args, **kwargs):
if (self.color == True and record.levelno in self.COLOR_CODES):
record.color_on = self.COLOR_CODES[record.levelno]
record.color_off = self.RESET_CODE
else:
record.color_on = ""
record.color_off = ""
return super(LogFormatter, self).format(record, *args, **kwargs)
def set_up_logging(console_log_output, console_log_level, console_log_color, logfile_file, logfile_log_level, logfile_log_color, log_line_template):
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
console_log_output = console_log_output.lower()
if (console_log_output == "stdout"):
console_log_output = sys.stdout
elif (console_log_output == "stderr"):
console_log_output = sys.stderr
else:
print("Failed to set console output: invalid output: '%s'" % console_log_output)
return False
console_handler = logging.StreamHandler(console_log_output)
try:
console_handler.setLevel(console_log_level.upper())
except:
print("Failed to set console log level: invalid level: '%s'" % console_log_level)
return False
console_formatter = LogFormatter(fmt=log_line_template, color=console_log_color)
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)
try:
logfile_handler = logging.FileHandler(logfile_file)
except Exception as exception:
print("Failed to set up log file: %s" % str(exception))
return False
try:
logfile_handler.setLevel(logfile_log_level.upper())
except:
print("Failed to set log file log level: invalid level: '%s'" % logfile_log_level)
return False
logfile_formatter = LogFormatter(fmt=log_line_template, color=logfile_log_color)
logfile_handler.setFormatter(logfile_formatter)
logger.addHandler(logfile_handler)
return True
def main():
script_name = os.path.splitext(os.path.basename(sys.argv[0]))[0]
if (not set_up_logging(console_log_output="stdout", console_log_level="warning", console_log_color=True,
logfile_file=script_name + ".log", logfile_log_level="debug", logfile_log_color=False,
log_line_template="%(color_on)s[%(created)d] [%(threadName)s] [%(levelname)-8s] %(message)s%(color_off)s")):
print("Failed to set up logging, aborting.")
return 1
logging.debug("Debug message")
logging.info("Info message")
logging.warning("Warning message")
logging.error("Error message")
logging.critical("Critical message")
if (__name__ == "__main__"):
sys.exit(main())
关于 Microsoft Windows:
如果想要在 Microsoft Windows 的经典 命令提示符 中显示带颜色的输出,需要添加一些额外的代码。但在新的支持带颜色的输出功能的终端应用中,则不需要这样做。
有两种选择:
1) 使用 Python 包 colorama (过滤发送到 stdout 和 stderr 的输出并将逃逸序列转换为本地Windows API调用;适用于 Windows XP 及更高版本):
import colorama
colorama.init()
2) 使用以下函数启用ANSI终端模式(通过设置ENABLE_VIRTUAL_TERMINAL_PROCESSING
标志使终端解释转义序列;有关更多信息,请参见此处、此处、此处和此处;适用于 Windows 10 及以后版本):
import sys
import ctypes
def windows_enable_ansi_terminal_mode():
if (sys.platform != "win32"):
return None
try:
kernel32 = ctypes.windll.kernel32
result = kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
if (result == 0): raise Exception
return True
except:
return False