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 01 Python
在Python的Django框架中为代码添加注释的方法
Jul 16 Python
pandas数据框,统计某列数据对应的个数方法
Apr 11 Python
Python3中的列表生成式、生成器与迭代器实例详解
Jun 11 Python
对Python定时任务的启动和停止方法详解
Feb 19 Python
在pyqt5中QLineEdit里面的内容回车发送的实例
Jun 21 Python
PyQT5 QTableView显示绑定数据的实例详解
Jun 25 Python
numpy.array 操作使用简单总结
Nov 08 Python
Python for循环及基础用法详解
Nov 08 Python
PyCharm中如何直接使用Anaconda已安装的库
May 28 Python
Python如何进行时间处理
Aug 06 Python
教你用python实现一个无界面的小型图书管理系统
May 21 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实现多条件查询实例代码
2010/07/17 PHP
thinkphp3.2中Lite文件替换框架入口文件或应用入口文件的方法
2015/05/21 PHP
header与缓冲区之间的深层次分析
2016/07/30 PHP
PHP实现导出带样式的Excel
2016/08/28 PHP
PHP验证码无法显示的原因及解决办法
2017/08/11 PHP
在laravel中实现将查询的对象转换为多维数组的函数
2019/10/21 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
2019/12/30 PHP
使用jQuery模板来展现json数据的代码
2010/10/22 Javascript
关于jquery的多个选择器的使用示例
2013/10/18 Javascript
JS常用字符串处理方法应用总结
2014/05/22 Javascript
jQuery+ajax实现鼠标单击修改内容的思路
2014/06/29 Javascript
简单方法判断JavaScript对象为null或者属性为空
2014/09/26 Javascript
使用js画图之正弦曲线
2015/01/12 Javascript
微信小程序 教程之模板
2016/10/18 Javascript
web 屏蔽BackSpace键实例代码
2016/12/24 Javascript
react中的ajax封装实例详解
2017/10/17 Javascript
JavaScript实现删除数组重复元素的5种常用高效算法总结
2018/01/18 Javascript
JavaScript事件发布/订阅模式原理与用法分析
2018/08/21 Javascript
vue2.0实现的tab标签切换效果(内容可自定义)示例
2019/02/11 Javascript
js实现页面多个日期时间倒计时效果
2019/06/20 Javascript
微信浏览器下拉黑边解决方案 wScroollFix
2020/01/21 Javascript
Python修改Excel数据的实例代码
2013/11/01 Python
python解析xml模块封装代码
2014/02/07 Python
python实现从网络下载文件并获得文件大小及类型的方法
2015/04/28 Python
基于Pandas读取csv文件Error的总结
2018/06/15 Python
python 列表降维的实例讲解
2018/06/28 Python
详解python数据结构和算法
2019/04/18 Python
Python缓存技术实现过程详解
2019/09/25 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
2019/11/19 Python
django执行原始查询sql,并返回Dict字典例子
2020/04/01 Python
Django用户登录与注册系统的实现示例
2020/06/03 Python
浅谈python出错时traceback的解读
2020/07/15 Python
Django中template for如何使用方法
2021/01/31 Python
法拉利英国精品店:Ferraris Boutique UK
2019/07/20 全球购物
医院总经理职责
2013/12/26 职场文书
银行竞聘演讲稿范文
2014/04/23 职场文书