基本使用
2019-10-13 22:46:12.367 | DEBUG | __main__:<module>:4 - this is a debug message
默认的输出格式 有时间、级别、模块名、行号以及日志信息,不需要手动创建 logger, 直接输出到控制台的
from loguru import logger
logger.debug('this is a debug message')
添加文件
from loguru import logger
logger.add('runtime.log')
logger.debug('this is a debug')
详细使用
loguru 对输出到文件的配置
有非常强大的支持,
支持输出到多个文件
,分级别分别输出
,过大创建新文件
,过久自动删除
等等
add
add 方法
就相当于给 logger 添加了一个 Handler
def add(
self,
sink,
*,
level=_defaults.LOGURU_LEVEL,
format=_defaults.LOGURU_FORMAT,
filter=_defaults.LOGURU_FILTER,
colorize=_defaults.LOGURU_COLORIZE,
serialize=_defaults.LOGURU_SERIALIZE,
backtrace=_defaults.LOGURU_BACKTRACE,
diagnose=_defaults.LOGURU_DIAGNOSE,
enqueue=_defaults.LOGURU_ENQUEUE,
catch=_defaults.LOGURU_CATCH,
**kwargs
):
...
sink 可以传入一个 file 对象,例如 sys.stderr 或者 open('file.log', 'w') 都可以。
sink 可以直接传入一个 str 字符串或者 pathlib.Path 对象,其实就是代表文件路径的,如果识别到是这种类型,它会自动创建对应路径的日志文件并将日志输出进去。
sink 可以是一个方法,可以自行定义输出实现。
sink 可以是一个 logging 模块的 Handler,比如 FileHandler、StreamHandler 等等,或者上文中我们提到的 CMRESHandler 照样也是可以的,这样就可以实现自定义 Handler 的配置。
sink 还可以是一个自定义的类,具体的实现规范可以参见官方文档
All sinks added to the logger are thread-safe
by default.
logger.add('runtime.log', format="{time} {level} {message}", filter="my_module", level="INFO")
- 删除
sink
添加 sink
之后对其进行删除,相当于重新刷新并写入新的内容
删除的时候根据刚刚 add 方法返回的 id 进行删除即可
from loguru import logger
trace = logger.add('runtime.log')
logger.debug('this is a debug message') # 获取返回值
logger.remove(trace)
logger.debug('this is another debug message')
rotation
配置
1 每 500MB 存储一个文件, 每个 log 文件过大就会新创建一个 log 文件
logger.add('runtime_{time}.log', rotation="500 MB")
# time 占位符,这样在生成时可以自动将时间替换进去,生成一个文件名包含时间的 log 文件
2 定时创建 log 文件
logger.add('runtime_{time}.log', rotation='00:00')
# 每天 0 点新创建一个 log 文件输出
logger.add('runtime_{time}.log', rotation='1 week')
# 一周创建一个 log 文件
retention
配置
retention 这个参数可以配置日志的最长保留时间
logger.add('runtime.log', retention='10 days')
# 保留最新 10 天的 log
compression
配置
文件的压缩格式
logger.add('runtime.log', compression='zip')
@logger.catch
获取子线程中的异常
from loguru import logger
from threading import Thread
@logger.catch()
def my_func(a, b):
return 1 / (a + b)
logger.add("threading_log.log")
logger.info("main start")
t = Thread(target=my_func, args=(0, 0))
t.start()
t.join()
logger.info("main end")
enqueue
和 looger的complete
函数
默认情况下,logger是线程安全
的。
logger.add("somefile.log", enqueue=True)
使用 complete
函数 和 enqueue
参数 保证进程安全, 异步的日志操作
# 多进程
def process():
logger.info("Message sent from the child")
logger.complete()
logger.add(sys.stderr, enqueue=True)
process = multiprocessing.Process(target=process)
process.start()
process.join()
# Message sent from the child
# 协程
async def sink(message):
await asyncio.sleep(0.1) # IO processing...
print(message, end="")
async def work():
logger.info("Start")
logger.info("End")
await logger.complete() # complete
logger.add(sink)
asyncio.run(work())
backtrace
,diagnose
Fully descriptive exceptions
显示全部的 trace, 但是 may leak sensitive data in prod
logger.add("out.log", backtrace=True, diagnose=True) # Caution, may leak sensitive data in prod
def func(a, b):
return a / b
def nested(c):
try:
func(5, c)
except ZeroDivisionError:
logger.exception("What?!")
nested(0)