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当中的字符串和编码
Apr 25 Python
举例讲解Python中的身份运算符的使用方法
Oct 13 Python
python处理Excel xlrd的简单使用
Sep 12 Python
基于循环神经网络(RNN)的古诗生成器
Mar 26 Python
Python实现的FTP通信客户端与服务器端功能示例
Mar 28 Python
python3实现磁盘空间监控
Jun 21 Python
Python中新式类与经典类的区别详析
Jul 10 Python
django 单表操作实例详解
Jul 30 Python
Python切割图片成九宫格的示例代码
Mar 10 Python
python函数中将变量名转换成字符串实例
May 11 Python
Python colormap库的安装和使用详情
Oct 06 Python
Pyhton爬虫知识之正则表达式详解
Apr 01 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
一个严格的PHP Session会话超时时间设置方法
2014/06/10 PHP
php的curl封装类用法实例
2014/11/07 PHP
php实现按指定大小等比缩放生成上传图片缩略图的方法
2014/12/15 PHP
PHP基于递归算法解决兔子生兔子问题
2018/05/11 PHP
PHP切割汉字的常用方法实例总结
2019/04/27 PHP
JavaScript 特殊字符
2007/04/05 Javascript
js树形控件脚本代码
2008/07/24 Javascript
jQuery帮助之CSS尺寸(五)outerHeight、outerWidth
2009/11/14 Javascript
JQuery AJAX提交中文乱码的解决方案
2010/07/02 Javascript
jQuery隔行变色与普通JS写法的对比
2013/04/21 Javascript
js面向对象之公有、私有、静态属性和方法详解
2015/04/17 Javascript
jQuery插件实现无缝滚动特效
2015/11/24 Javascript
js编写贪吃蛇的小游戏
2020/08/24 Javascript
深入解析JavaScript中的arguments对象
2016/06/12 Javascript
jquery通过name属性取值的简单实现方法
2016/06/20 Javascript
轻松实现js选项卡切换效果
2016/09/24 Javascript
原生JS实现图片轮播切换效果
2016/12/15 Javascript
ES6之模版字符串的具体使用
2018/05/17 Javascript
Vue.js图片预览插件使用详解
2018/08/27 Javascript
node中IO以及定时器优先级详解
2019/05/10 Javascript
vue路由切换时取消之前的所有请求操作
2020/09/01 Javascript
vue项目页面嵌入代码块vue-prism-editor的实现
2020/10/30 Javascript
python实现同时给多个变量赋值的方法
2015/04/30 Python
5分钟 Pipenv 上手指南
2018/12/20 Python
基于python traceback实现异常的获取与处理
2019/12/13 Python
python实现图像全景拼接
2020/03/27 Python
安装pyinstaller遇到的各种问题(小结)
2020/11/20 Python
AmazeUI折叠式卡片布局,整合内容列表、表格组件实现
2020/08/20 HTML / CSS
Yummie官方网站:塑身衣和衣柜必需品
2019/10/29 全球购物
实习老师离校感言
2014/02/03 职场文书
保护野生动物倡议书
2014/05/16 职场文书
青春飞扬演讲稿
2014/09/11 职场文书
开除通知书范本
2015/04/25 职场文书
2016公务员年度考核评语
2015/12/01 职场文书
导游词之吉林吉塔
2019/11/11 职场文书
python游戏开发之pygame实现接球小游戏
2022/04/22 Python