Python日志
Python记录系列.
三方库
loguru
pip install loguru
from loguru import logger
logger.add(sys.stderr, format="{time} {level} {message}", filter="my_module", level="INFO")
logger.add("file_{time}.log")
logger.add("file.log", format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}")
logging
- logger:logging.getLogger(name) , 以相同的名称多次调用getLogger()将永远返回相同Logger对象的引用
- config
- logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
- logging.config.dictConfig,
- logging.config.fileConfig
- Handlers: logging.handlers.RotatingFileHandler(LOG_FILENAME,maxBytes=1024,backupCount=5,)
基础用法
import logging
# 设置文件日志
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
# datefmt='%m-%d %H:%M',
filename='myapp.log',
filemode='w')
logging.getLogger().setLevel(logging.DEBUG)
# define a Handler which writes INFO messages or higher to the sys.stderr
console = logging.StreamHandler()
console.setLevel(logging.INFO)
# add the handler to the root logger
logging.getLogger().addHandler(console)
logger = logging.getLogger('myapp')
使用json配置文件
import os
import json
import logging.config
def setup_logging(
default_path='logging.json',
default_level=logging.INFO,
env_key='LOG_CFG'
):
"""Setup logging configuration
"""
path = default_path
value = os.getenv(env_key, None)
if value:
path = value
if os.path.exists(path):
with open(path, 'rt') as f:
config = json.load(f)
logging.config.dictConfig(config)
else:
logging.basicConfig(level=default_level)
if __name__ == '__main__':
setup_logging()
logger = logging.getLogger()
logger.info("info log test")
logger.error("error log test")
配置文件例子:
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"simple": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "simple",
"stream": "ext://sys.stdout"
},
"info_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "INFO",
"formatter": "simple",
"filename": "info.log",
"maxBytes": 10485760,
"backupCount": 20,
"encoding": "utf8"
},
"error_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "ERROR",
"formatter": "simple",
"filename": "errors.log",
"maxBytes": 10485760,
"backupCount": 20,
"encoding": "utf8"
}
},
"loggers": {
"my_module": {
"level": "ERROR",
"handlers": ["console"],
"propagate": "no"
}
},
"root": {
"level": "INFO",
"handlers": ["console", "info_file_handler", "error_file_handler"]
}
}
日志Tips
获取当前ROOT日志级别
logging.getLogger().isEnabledFor(logging.DEBUG)
# 10 DEBUG 20 INFO
logging.getLogger().getEffectiveLevel()
禁用Requests日志
NullHandler用来禁用第三方库的日志.
两种方式:
import logging
requests_log = logging.getLogger("requests")
requests_log.addHandler(logging.NullHandler())
requests_log.propagate = False
import requests
import logging
for key in logging.Logger.manager.loggerDict:
print(key)# requests.packages.urllib3.connectionpool
logging.getLogger('requests').setLevel(logging.CRITICAL)
#
requests.packages.urllib3.disable_warnings()
urllib3
import urllib3
# 禁用自签证书
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
logging.getLogger('urllib3.connectionpool').setLevel(logging.CRITICAL)
异常处理
- raise: 没有参数的raise会再次抛出最后的异常
- try-except-else: 只在没有异常时执行else(在final之前)
logger.exception("something uncaught happened")
# 等价于
logger.error("something uncaught happened", exc_info=True)
规则
- 使用最适合当前情况的异常
- 只在你能对异常做处理时捕获
- 不要在异常块直接pass
- 需要时创建自定义类型错误
常见内置异常
用户自定义异常的基类: Exception
- SystemExit
- KeyboardInterrupt
- NotImplementedError
- EnvironmentError
- IOError
- ImportError
特殊使用
忽略异常:
# Ignore Exceptions intended
from contextlib import suppress
with suppress(FileNotFoundError):
shutil.rmtree(path)