Python线上环境使用日志的及配置文件


Posted in Python onJuly 28, 2019

目录

  • 瞎比比
  • 与 print 相比 logging 有什么优势?
  • 基础用法
  • 保存到文件
  • 多模块使用 logging
  • 使用配置文件配置 logging

瞎比比

这篇文章其实早在一个月之前就写好了。奈何,加班猛如虎,真的怕了。直至今天才幸运地有了个双休,赶紧排版一下文章发布了。以下为正文。 在初学 Python 的时候,我们使用

print("hello world")

输出了我们的第一行代码。在之后的日子里,便一直使用 print 进行调试(当然,还有 IDE 的 debug 模式)。但是,当你在线上运行 Python 脚本的时候,你并不可能一直守着你的运行终端。可是如果不守着的话,每当出现 bug ,错误又无从查起。这个时候,你需要对你的调试工具进行更新换代了,这里我推荐一个优雅的调试工具 logging。

与 print 相比 logging 有什么优势?

那既然我推荐这个工具,它凭什么要被推荐呢?且来看看它有什么优势:

  • 可以输出到多处,例如:在输出到控制台的同时,可以保存日志到日志文件里面,或者保存到其他远程服务器
  • 可以设置日志等级,DEBUG、INFO、ERROR等,在不同的环境(调试环境、线上环境)使用不同的等级来过滤日志,使用起来很方便
  • 配置灵活,可保存到配置文件,格式化输出

基础用法

下面涉及到的代码我都省略了导包部分,详见源码(后台回复 logging 获取源码)

base_usage.py

logging.basicConfig(level=log_level, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
logger.info("Log level info")
logger.debug("Log level debug")
logger.warning("Log level warning")
# 捕获异常,并打印出出错行数
try:
  raise Exception("my exception")
except (SystemExit, KeyboardInterrupt):
  raise
except Exception:
  logger.error("there is an error =>", exc_info=True)

level为日志等级,分为:

FATAL:致命错误
CRITICAL:特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用
ERROR:发生错误时,如IO操作失败或者连接问题
WARNING:发生很重要的事件,但是并不是错误时,如用户登录密码错误
INFO:处理请求或者状态变化等日常事务
DEBUG:调试过程中使用DEBUG等级,如算法中每个循环的中间状态

foamat可以格式化输出,其参数有如下:

%(levelno)s:打印日志级别的数值
%(levelname)s:打印日志级别的名称
%(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s:打印当前执行程序名
%(funcName)s:打印日志的当前函数
%(lineno)d:打印日志的当前行号
%(asctime)s:打印日志的时间
%(thread)d:打印线程ID
%(threadName)s:打印线程名称
%(process)d:打印进程ID
%(message)s:打印日志信息

捕获异常,以下两行代码都具有相同的作用

logger.exception(msg,_args)
logger.error(msg,exc_info = True,_args)

保存到文件,并输出到命令行

这个用法直接 copy 使用就行

import logging
# 写入文件
import logging
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler("info.log")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info("Log level info")
logger.debug("Log level debug")
logger.warning("Log level warning")
# 写入文件,同时输出到屏幕
import logging
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("info.log")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(handler)
logger.addHandler(console)
logger.info("Log level info")
logger.debug("Log level debug")
logger.warning("Log level warning")

多模块使用 logging

被调用者的日志格式会与调用者的日志格式一样 main.py

# -*- coding: utf-8 -*-
__auth__ = 'zone'
__date__ = '2019/6/17 下午11:46'
'''
公众号:zone7

小程序:编程面试题库

'''
import os
import logging
from python.logging_model.code import sub_of_main
logger = logging.getLogger("zone7Model")
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(console)
sub = sub_of_main.SubOfMain()
logger.info("main module log")
sub.print_some_log()
sub_of_main.py
# -*- coding: utf-8 -*-
__auth__ = 'zone'
__date__ = '2019/6/17 下午11:47'
'''

公众号:zone7

小程序:编程面试题库

'''
import logging
module_logger = logging.getLogger("zone7Model.sub.module")
class SubOfMain(object):
  def __init__(self):
    self.logger = logging.getLogger("zone7Model.sub.module")
    self.logger.info("init sub class")
  def print_some_log(self):
    self.logger.info("sub class log is printed")

def som_function():
  module_logger.info("call function some_function")

使用配置文件配置 logging

这里分别给出了两种配置文件的使用案例,都分别使用了三种输出,输出到命令行、输出到文件、将错误信息独立输出到一个文件

log_cfg.json
{
  "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":["info_file_handler2"],
      "propagate":"no"
    }
  },
  "root":{
    "level":"INFO",
    "handlers":["console","info_file_handler","error_file_handler"]
  }
}

通过 json 文件读取配置:

import json
import logging.config
import os
def set_log_cfg(default_path="log_cfg.json", default_level=logging.INFO, env_key="LOG_CFG"):
  path = default_path
  value = os.getenv(env_key, None)
  if value:
    path = value
  if os.path.exists(path):
    with open(path, "r") as f:
      config = json.load(f)
      logging.config.dictConfig(config)
  else:
    logging.basicConfig(level=default_level)
def record_some_thing():
  logging.info("Log level info")
  logging.debug("Log level debug")
  logging.warning("Log level warning")
if __name__ == "__main__":
  set_log_cfg(default_path="log_cfg.json")
  record_some_thing()
log_cfg.yaml
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: [info_file_handler]
      propagate: no
root:
  level: INFO
  handlers: [console,info_file_handler,error_file_handler]

通过 yaml 文件读取配置:

import yaml
import logging.config
import os
def set_log_cfg(default_path="log_cfg.yaml", default_level=logging.INFO, env_key="LOG_CFG"):
  path = default_path
  value = os.getenv(env_key, None)
  if value:
    path = value
  if os.path.exists(path):
    with open(path, "r") as f:
      config = yaml.load(f)
      logging.config.dictConfig(config)
  else:
    logging.basicConfig(level=default_level)
def record_some_thing():
  logging.info("Log level info")
  logging.debug("Log level debug")
  logging.warning("Log level warning")
if __name__ == "__main__":
  set_log_cfg(default_path="log_cfg.yaml")
  record_some_thing()

总结

以上所述是小编给大家介绍的Python线上环境使用日志的及配置文件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
python获取当前计算机cpu数量的方法
Apr 18 Python
python爬虫实战之爬取京东商城实例教程
Apr 24 Python
答题辅助python代码实现
Jan 16 Python
Python实现的计算马氏距离算法示例
Apr 03 Python
python框架Django实战商城项目之工程搭建过程图文详解
Mar 09 Python
windows上彻底删除jupyter notebook的实现
Apr 13 Python
解决python执行较大excel文件openpyxl慢问题
May 15 Python
Python暴力破解Mysql数据的示例
Nov 09 Python
python绘制雷达图实例讲解
Jan 03 Python
python+selenium实现12306模拟登录的步骤
Jan 21 Python
教你怎么用python爬取爱奇艺热门电影
May 20 Python
Python人工智能之混合高斯模型运动目标检测详解分析
Nov 07 Python
Django 实现admin后台显示图片缩略图的例子
Jul 28 #Python
处理python中多线程与多进程中的数据共享问题
Jul 28 #Python
在django中图片上传的格式校验及大小方法
Jul 28 #Python
python之生产者消费者模型实现详解
Jul 27 #Python
python单线程下实现多个socket并发过程详解
Jul 27 #Python
如何使用python操作vmware
Jul 27 #Python
利用python计算windows全盘文件md5值的脚本
Jul 27 #Python
You might like
浅析echo(),print(),print_r(),return之间的区别
2013/11/27 PHP
PHP数组与字符串互相转换实例
2020/05/05 PHP
Prototype PeriodicalExecuter对象 学习
2009/07/19 Javascript
Mootools 1.2教程 输入过滤第一部分(数字)
2009/09/15 Javascript
顶部缓冲下拉菜单导航特效的JS代码
2013/08/27 Javascript
Chrome下ifame父窗口调用子窗口的问题示例探讨
2014/03/17 Javascript
ECMAScript5中的对象存取器属性:getter和setter介绍
2014/12/08 Javascript
javascript数据结构之二叉搜索树实现方法
2015/11/25 Javascript
js利用正则表达式检验输入内容是否为网址
2016/07/05 Javascript
Javascript 两种刷新方法以及区别和适用范围
2017/01/17 Javascript
重新理解JavaScript的六种继承方式
2017/03/24 Javascript
JavaScript实现获取远程的html到当前页面中
2017/03/26 Javascript
ES6学习笔记之正则表达式和字符串正则方法分析
2017/04/25 Javascript
vue 使用自定义指令实现表单校验的方法
2018/08/28 Javascript
javaScript实现游戏倒计时功能
2018/11/17 Javascript
bootstrap与pagehelper实现分页效果
2018/12/29 Javascript
javascript实现5秒倒计时并跳转功能
2019/06/20 Javascript
[02:12]2019完美世界全国高校联赛(春季赛)报名开启
2019/03/01 DOTA
python下载文件时显示下载进度的方法
2015/04/02 Python
Python使用multiprocessing创建进程的方法
2015/06/04 Python
Python 基础教程之str和repr的详解
2017/08/20 Python
详解python读取和输出到txt
2019/03/29 Python
Python远程视频监控程序的实例代码
2019/05/05 Python
Python如何将图像音视频等资源文件隐藏在代码中(小技巧)
2020/02/16 Python
jupyter notebook oepncv 显示一张图像的实现
2020/04/24 Python
基于python实现操作git过程代码解析
2020/07/27 Python
html5中嵌入视频自动播放的问题解决
2020/05/25 HTML / CSS
中文专业毕业生自荐信
2013/10/28 职场文书
2014高考励志标语
2014/06/05 职场文书
收款委托书范本
2014/09/11 职场文书
2014年青年志愿者工作总结
2014/12/09 职场文书
合同审查法律意见书
2015/06/04 职场文书
初三语文教学反思
2016/03/03 职场文书
python实现批量移动文件
2021/04/05 Python
HTML5中 rem适配方案与 viewport 适配问题详解
2021/04/27 HTML / CSS
MySQL中EXPLAIN语句及用法
2022/05/20 MySQL