python日志记录模块实例及改进
作者:sxhlinux 发布时间:2021-03-14 12:49:09
python 打印对象的所有属性值:
def prn_obj(obj):
print '\n'.join(['%s:%s' % item for item in obj.__dict__.items()])
Python logger对象属性(由上述函数获取的)
name:get_data
parent:<logging.RootLogger instance at 0x1d8bd88>
handlers:[<logging.FileHandler instance at 0x21bcc68>]
level:10
disabled:1 #当前的logger是否有效,默认为0
manager:<logging.Manager instance at 0x1d8bea8>
propagate:0 #是否将本级日志
filters:[]
部分日志无法输出
File:logger.conf
[formatters]
keys=default
[formatter_default]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
class=logging.Formatter
[handlers]
keys=console, error_file
[handler_console]
class=logging.StreamHandler
formatter=default
args=tuple()
[handler_error_file]
class=logging.FileHandler
level=INFO
formatter=default
args=("logger.log", "a")
[loggers]
keys=root
[logger_root]
level=DEBUG
formatter=default
handlers=console,error_file
File:logger.py
#!/bin/env python
import logging
from logging.config import logging
class Test(object):
"""docstring for Test"""
def __init__(self):
logging.config.fileConfig("logger.conf")
self.logger = logging.getLogger(__name__)
def test_func(self):
self.logger.error('test_func function')
class Worker(object):
"""docstring for Worker"""
def __init__(self):
logging.config.fileConfig("logger.conf")
self.logger = logging.getLogger(__name__)
data_logger = logging.getLogger('data')
handler = logging.FileHandler('./data.log')
fmt = logging.Formatter('%(asctime)s|%(message)s')
handler.setFormatter(fmt)
data_logger.addHandler(handler)
data_logger.setLevel(logging.DEBUG)
self.data_logger = data_logger
def test_logger(self):
self.data_logger.error("test_logger function")
instance = Test()
self.data_logger.error("test_logger output")
instance.test_func()
def main():
worker = Worker()
worker.test_logger()
if __name__ == '__main__':
main()
问题一:测试过程中,只能打印出test_logger function一条语句
问题二:明明只在data_logger中打印出语句,但是logger的日志中也出现了相关的日志。
问题一解决方案:
利用python -m pdb logger.py 语句对脚本进行调试发现,在执行instance = Test()语句后,通过print '\n'.join(['%s:%s' % item for item in self.data_logger.__dict__.items()])调试语句看到data_logger的disable属性值由0变成了True,此时logger的对应属性也发生了相同的变化。这种变化导致了logger对象停止记录日志。参考python logging模块的相关手册发现“The fileConfig() function takes a default parameter, disable_existing_loggers, which defaults to True for reasons of backward compatibility. This may or may not be what you want, since it will cause any loggers existing before the fileConfig() call to be disabled unless they (or an ancestor) are explicitly named in the configuration.” 的说明,即调用fileconfig()函数会将之前存在的所有logger禁用。在python 2.7版本该fileConfig()函数添加了一个参数,logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True),可以显式的将disable_existing_loggers设置为FALSE来避免将原有的logger禁用。将上述代码中的Test类中的logging.config.fileConfig函数改成logging.config.fileConfig("./logger.conf", disable_existing_loggers=0)就可以解决问题。 不过该代码中由于位于同一程序内,可以直接用logging.getLogger(LOGGOR_NAME)函数引用同一个logger,不用再调用logging.config.fileConfig函数重新加载一遍了。
问题二解决方案:
logger对象有个属性propagate,如果这个属性为True,就会将要输出的信息推送给该logger的所有上级logger,这些上级logger所对应的handlers就会把接收到的信息打印到关联的日志中。logger.conf配置文件中配置了相关的root logger的属性,这个root logger就是默认的logger日志。
修改后的如下:
File:logger.conf
[formatters]
keys=default, data
[formatter_default]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
class=logging.Formatter
[formatter_data]
format=%(asctime)s|%(message)s
class=logging.Formatter
[handlers]
keys=console, error_file, data_file
[handler_console]
class=logging.StreamHandler
formatter=default
args=tuple()
[handler_error_file]
class=logging.FileHandler
level=INFO
formatter=default
args=("logger.log", "a")
[handler_data_file]
class=logging.FileHandler
level=INFO
formatter=data
args=("data_new.log", "a")
[loggers]
keys=root, data
[logger_root]
level=DEBUG
handlers=console,error_file
[logger_data]
level=DEBUG
handlers=data_file
qualname=data
propagate=0
File:logger.py
#!/bin/env python
import logging
from logging.config import logging
class Test(object):
"""docstring for Test"""
def __init__(self):
self.logger = logging.getLogger(__name__)
def test_func(self):
self.logger.error('test_func function')
class Worker(object):
"""docstring for Worker"""
def __init__(self):
logging.config.fileConfig("logger.conf")
self.logger = logging.getLogger(__name__)
self.data_logger = logging.getLogger('data')
def test_logger(self):
self.data_logger.error("test_logger function")
instance = Test()
self.data_logger.error("test_logger output")
instance.test_func()
def main():
worker = Worker()
worker.test_logger()
if __name__ == '__main__':
main()
猜你喜欢
- python解释器默认编码(python2与python3的区别一)python2 解释器默认编码:asciipython3 解释器默认编码
- 当你的查询相对简单的时候,每次从头开始创建SQL语句也不费什么工夫,不过,复杂的查询就不同了,每次都从头来会产生很多开发错误。因此,一旦让S
- 可试试下面这个方法,但要保证在FORM中使用的Input Name都和数据库中使用的是一样的:upfiles.asp<% &
- Random库主要包含返回随机数的函数,主要用于普通的随机数生成的程序,如果对随机性有特殊要求,比如加密等,可以用函数os.urandom(
- atom(一款开源的代码编辑器)是github专门为程序员推出的一个跨平台文本编辑器。具有简洁和直观的图形用户界面,并有很多有趣的特点:支持
- BN与Dropout共同使用出现的问题BN和Dropout单独使用都能减少过拟合并加速训练速度,但如果一起使用的话并不会产生1+1>2
- 1.哆啦A梦“只要把愿望系在竹竿上请求月亮女神,心愿便能达成”。我超喜欢这句话。哆啦A梦的创造要追溯
- Python没有类似于Java的private关键字, 但也可以为类定义私有属性. 只需将属性命名变为以__开头, 例如 __field.示
- 如果有一个多任务多loss的网络,那么在训练时,loss是如何工作的呢?比如下面:model = Model(inputs = input,
- php魔术方法在php类保留方法中以 “__”两个下划线开头的函数称为魔术方法,我的理解为php类设
- 1、使用mysqli扩展库 预处理技术 mysqli stmt 向数据库添加3个用户<?php /
- 代码中用到了nextpow2,其中n = nextpow2(x) 表示最接近x的2的n次幂。#!/usr/bin/env pythonimp
- 1 引言形态学运算是针对二值图像依据数学形态学集合论方法发展起来的图像处理的方法.其主要内容是设计一整套的变换概念和算法,用以描述图像的基本
- 这里说的“相对路径”是相对于“主调文件”所在的文件夹。#include file #include file后面跟的是文件的“相对路径”,不
- python书写爬虫的一个框架,它也提供了多种类型爬虫的基类,scrapy用途广泛,可以用于数据挖掘、监测和自动化测试首先要先安装pytho
- 本文实例讲述了PHP与Web页面交互操作。分享给大家供大家参考,具体如下:Web交互1.Web表单交互当表单的method属性提交方式为PO
- 前言相当不错的 Javascript 编程风格规范,建议大家采用此规范编写 Javascript。原文链接: http://dojotool
- 此BUG最初是在《前端观察》网站刊登,这里再描述一下,代码如下:<style>*{ padding:0; m
- 选项default-charaset-set=utf8;然后创建一个数据表 create table a_table(b varchar(2
- 我们需要将【小组销量排名表.xlsx】通过邮件发送给【组长邮箱.xlsx】中的各个组长。这里会学一个新的知识点—&