在Python环境下,logging是一个很好的用于处理日志的扩展包。平时使用时一般直接import logging后,调用logging.debug(“info”)方法打印日志。一般情况下够用,但是在需要涉及到复杂的日志功能(例如分级、写文件、归档等)后,则需要深入地对logging进行配置。通常情况下会使用yaml配置。
创建一个loggingconfigyaml.yaml文件,内容如下:
version: 1
disable_existing_loggers: False
formatters:
simple:
format: '%(asctime)s %(levelname)s %(message)s'
upgrade:
format: "%(asctime)s -Loc %(filename)s -Pid %(process)d -%(name)s -%(levelname)s - %(message)s"
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
all_file_handler:
class: logging.handlers.RotatingFileHandler
level: DEBUG
formatter: upgrade
filename: ./logs/all_logs/all_log.log
maxBytes: 10485760
backupCount: 50
encoding: utf8
server_file_handler:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: upgrade
filename: ./logs/server_logs/server.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
loggers:
server:
level: DEBUG
handlers: [server_file_handler]
propagate: true
root:
level: DEBUG
handlers: [console, all_file_handler]
通过Python的yaml包读取并加载配置,对logging应用该配置。
import yaml
import logging.config
import os
def test():
with open(file="loggingconfigyaml.yaml", mode='r', encoding="utf-8")as file:
logging_yaml = yaml.load(stream=file, Loader=yaml.FullLoader)
handlers = logging_yaml['handlers']
for key, value in handlers.items():
if 'filename' in value:
log_path = (os.path.split(value['filename'])[0])
if not os.path.exists(log_path):
os.makedirs(log_path)
logging.config.dictConfig(config=logging_yaml)
root = logging.getLogger()
server = logging.getLogger("server")
print("rootlogger:", root.handlers)
print("serverlogger:", server.handlers)
print("子记录器与根记录器的handler是否相同:", root.handlers[0] == server.handlers[0])
if __name__ == '__main__':
test()
带色彩的日志配置,移步gist.github - kingspp/logging.py:
logging.py:
import os
import yaml
import logging.config
import logging
import coloredlogs
def setup_logging(default_path='logging.yaml', default_level=logging.INFO, env_key='LOG_CFG'):
| **@author:** Prathyush SP
| Logging Setup
path = default_path
value = os.getenv(env_key, None)
if value:
path = value
if os.path.exists(path):
with open(path, 'rt') as f:
try:
config = yaml.safe_load(f.read())
logging.config.dictConfig(config)
coloredlogs.install()
except Exception as e:
print(e)
print('Error in Logging Configuration. Using default configs')
logging.basicConfig(level=default_level)
coloredlogs.install(level=default_level)
else:
logging.basicConfig(level=default_level)
coloredlogs.install(level=default_level)
print('Failed to load configuration file. Using default configs')
logging.yaml:
version: 1
disable_existing_loggers: true
formatters:
standard:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
error:
format: "%(levelname)s <PID %(process)d:%(processName)s> %(name)s.%(funcName)s(): %(message)s"
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: standard
stream: ext://sys.stdout
info_file_handler:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: standard
filename: /tmp/info.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
error_file_handler:
class: logging.handlers.RotatingFileHandler
level: ERROR
formatter: error
filename: /tmp/errors.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
debug_file_handler:
class: logging.handlers.RotatingFileHandler
level: DEBUG
formatter: standard
filename: /tmp/debug.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
critical_file_handler:
class: logging.handlers.RotatingFileHandler
level: CRITICAL
formatter: standard
filename: /tmp/critical.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
warn_file_handler:
class: logging.handlers.RotatingFileHandler
level: WARN
formatter: standard
filename: /tmp/warn.log
maxBytes: 10485760
backupCount: 20
encoding: utf8
root:
level: NOTSET
handlers: [console]
propogate: yes
loggers:
<module>:
level: INFO
handlers: [console, info_file_handler, error_file_handler, critical_file_handler, debug_file_handler, warn_file_handler]
propogate: no
<module.x>:
level: DEBUG
handlers: [info_file_handler, error_file_handler, critical_file_handler, debug_file_handler, warn_file_handler]
propogate: yes
[1] logging — Python 的日志记录工具
[2] gist.github - kingspp/logging.py
[3] python之使用yaml文件配置logging日志
[4] coloredlogs
前言在Python环境下,logging是一个很好的用于处理日志的扩展包。平时使用时一般直接import logging后,调用logging.debug(“info”)方法打印日志。一般情况下够用,但是在需要涉及到复杂的日志功能(例如分级、写文件、归档等)后,则需要深入地对logging进行配置。通常情况下会使用yaml配置。实践创建一个loggingconfigyaml.yaml文件,内容如下:version: 1disable_existing_loggers: Falseformat
logger = log.getLogger(__name__)
formatter = log.Formatter('%(asctime)s [%(name)s] :%(levelno)s:%(message)s', '%F %T')
# cre
一、使用logging.config.dictConfig()函数读取配置信息,参数是字典类型
with open(file=./loggingconfigyaml.yaml, mode='r', encoding=utf-8)as file:
logging_yaml = yaml.load(stream=file, Loader=yaml.FullLoader)
# print(logging_yaml)
# 配置logging日志:主要从文件中读取handler的配置、formatter(格式化日志样式)、logger记录器的配置
logging
logging.basicConfig(filename, filemode, format)其中format格式:%(levelno)s:打印日志级别的数值
%(levelname)s:打印日志级别的名称
%(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s:打印当前执行程序名
%(funcName)s:打印日志的当前函数
%(lineno)d
1、yml 配置文件配置
如上图所示,注意用于指定自定义的 filter 类的 key 是 () 而不是 class,详情请看官方文档说明:官方文档说明,斜体部分内容摘自官方文档:
The schema supports user-defined objects for handlers, filters and formatters. (Loggers do not need to have d...
记录日志是程序中尤其是 web 服务中的重要一环,恰到好处的日志记录可以帮助我们了解程序运行情况以及方便排(shuai)错(guo)。
logger 和 handler
如果使用 logging 不多,可能对 logger 和 handler 这两个概念不熟,大多数还是直接使用 logging.info() 来记录日志。
Python 官方给了一个流程图来说明日志消息(LogRecord)在 lo...
formatters:
simple:
format: "%(asctime)s [%(name)s] [%(levelname)s] :%(levelno)s: %(message)s"
1.配置共享
如果每个文件都配置logging,那就太繁琐了,logging提供了父子模块共享配置的机制,
会根据Logger的名称来自动加载父模块的配置.首先定义一个 main.py 文件:
import logging
import core
logger = logging.getLogger('main')
logger.setLevel(level=logging....
print(config['database']['host'])
print(config['database']['port'])
print(config['database']['username'])
print(config['database']['password'])
其中,`config.yaml`是yaml配置文件的文件名,`safe_load`方法可以安全地加载yaml文件并返回一个Python对象。在这个示例中,我们假设配置文件中有一个`database`配置项,其中包括`host`、`port`、`username`和`password`等子项。我们可以通过`config['database']['host']`等方式来访问这些子项的值。