笔记-python-module-logging.循环日志、多进程日志

1.      logging循环日志

循环日志分为按大小切分和按时间切分,对应实现类如下。

1.1.  RotatingFileHandler

常规文件回滚,需要指定文件名,encoding,maxBytes

如果maxbytes=0 或backupcount=0情况下不回滚,也就是只写到一个文件中。

新的日志永远写入filename.log,当它满的时候会将filename.log改名为filename.log.1或其它附加值;

def _set_file_handler(self, level=None):
    file_name = os.path.join(LOG_PATH, '{}.log'.format(self.name))
    file_handler =
RotatingFileHandler(file_name,
                                       maxBytes=5000,
                                       backupCount=5,
                                       encoding='utf-8')
    if not level:
        file_handler.setLevel(self.level)
    else:
        file_handler.setLevel(level)
    formatter = logging.Formatter('%(asctime)s
%(filename)s [line:%(lineno)d] %(levelname)s %(message)s'
)
    file_handler.setFormatter(formatter)
    self.file_handler
= file_handler
    self.addHandler(file_handler)

1.2.   
TimeRotatingFileHandler

def _set_time_rotating_handler(self, level=None):
    file_name = os.path.join(LOG_PATH, '{}.log'.format(self.name))
    time_handler =
logging.handlers.TimedRotatingFileHandler(file_name,
                                                            
when='h',
                                             
               interval=1,
                                                            
backupCount=5)
    if not level:
        time_handler.setLevel(self.level)
    else:
        time_handler.setLevel(level)
    formatter = logging.Formatter('%(asctime)s
%(filename)s [line:%(lineno)d] %(levelname)s %(message)s'
)
    time_handler.setFormatter(formatter)
    time_handler.suffix = "%Y-%m-%d_%H-%M-%S.log"
   
self.addHandler(time_handler)

需要注意的就是suffix的书写

1.3.   
总结

有几个坑要注意:

  1. 尽量使用Logger(__name__),一般情况下是不需要日志传递的
  2. 使用getLogger返回的实际是一个日志树
  3. logger实例初始化的propagate属性是true,即向父辈传递消息。而且消息是直接传递给handler。

2.     
multiprocessing and logging

logging 是线程安全的,handler 内部使用了
threading.RLock() 来保证同一时间只有一个线程能够输出。

但是,在使用 logging.FileHandler 时,多进程同时写一个日志文件是不支持的。

测试时发现多个进程写同一个文件是可以的,但部分文档说如果写长字符串时会出问题,测试写5000个字符的日志没问题,更长未确认。

在日志回滚时一定会出问题。

多进程写日志回滚的代码如下:

t
= self.rolloverAt - self.interval

if self.utc:

timeTuple = time.gmtime(t)

else:

timeTuple = time.localtime(t)

dfn = self.baseFilename + "." + time.strftime(self.suffix,
timeTuple)

if os.path.exists(dfn):

os.remove(dfn)

os.rename(self.baseFilename, dfn)

关键是在每个进程在过了rotate时间点之后写第一条日志时,都会执行这个doRollover,判断文件是否存在,如果存在则删除,改名,往新的.log中写入,等多个进程都做一遍后,前一周期的日志完全删除,本周期的日志也会有部分被删除。

术语一点的讲,就是在对文件操作时,没有对多进程进行一些约束。

解决办法:

  1. 解决文件重名问题:

既然问题是文件重名,那么就不让文件有重名,实际就是每个进程各写一个文件;有两种方法:

1)在文件名中加入pid,问题是老的pid不会被自动删除,无法自维护,不过可以通过定时任务检查并删除。

2)另一种方法是使用进程name做为logger名,在创建进程时给出不同的name,这样不会出现上面的问题;

不让文件重名的好处是可以单独追踪每个进程的日志,坏处是日志不集中。

建议使用这种方式,写日志有两种情况:

1-一般情况下每个进程是负责不同任务的,分开记录便于查找;

2-如果确实需要多个进程执行一样的任务,这时在查找日志记录时是比较麻烦的,不确定在哪个日志文件中,但考虑到工程效率,本方法也是可行的。

  1. 使用独立进程接收并写日志,logging提供了sockethandler;
  2. 改写logging的日志回滚类代码,不太喜欢,每次还得注意环境问题。
  3. 进程锁,效率问题,方法可行,但考虑各种因素,一般不会用。

2.1.   
一些问题:windows下多进程异常

报错:The "freeze_support()"
line can be omitted if the program is not going to be

原因及解决方法:

应该是在其它的子进程
里又开了进程,

把创建进程部分放到 if __name__ == ‘__main__’下即可

例:

if __name__ == '__main__':
    p = Process(target=func, name='my_process')
    p.daemon = True
   
p.start()
    p.join()
    print('process
execute complete.'
)

3.     
Logging.getLogger

getLogger是模块级的函数,实际是调用manager.getLogger()

def getLogger(name=None):

"""

Return a logger with the specified name, creating it if necessary.

If no name is specified, return the root logger.

"""

if name:

return Logger.manager.getLogger(name)

else:

return root

继续:manager.getLogger()

def
getLogger(self, name):

"""

Get a logger with the specified name (channel name), creating it

if it doesn't yet exist. This name is a dot-separated hierarchical

name, such as "a", "a.b", "a.b.c" or
similar.

If a PlaceHolder existed for the specified name [i.e. the logger

didn't exist but a child of it did], replace it with the created

logger and fix up the parent/child references which pointed to the

placeholder to now point to the logger.

"""

rv = None

if not isinstance(name, str):

raise TypeError('A logger name must be a string')

_acquireLock()

try:

if name in self.loggerDict:

rv = self.loggerDict[name]

if isinstance(rv, PlaceHolder):

ph = rv

rv = (self.loggerClass or
_loggerClass)(name)

rv.manager = self

self.loggerDict[name] = rv

self._fixupChildren(ph, rv)

self._fixupParents(rv)

else:

rv = (self.loggerClass or
_loggerClass)(name)

rv.manager = self

self.loggerDict[name] = rv

self._fixupParents(rv)

finally:

_releaseLock()

return rv

logging通过manager.loggerDict维护了一个logger列表,实现了相同名称返回同一个loogger。

如果logger名不存在,则创建一个新的:

rv = (self.loggerClass or
_loggerClass)(name)

基本等同于logger(name)

另外一点是logger的继承关系,是通过下面两个方法实现的

self._fixupChildren(ph, rv)

self._fixupParents(rv)

笔记-python-module-logging.循环日志、多进程日志的更多相关文章

  1. 转 使用Python的logging.config.fileConfig配置日志

    Python的logging.config.fileConfig方式配置日志,通过解析conf配置文件实现.文件 logglogging.conf 配置如下: [loggers]keys=root,f ...

  2. 解决多个py模块调用同一个python的logging模块,打印日志冲突问题

    前期对python中的logging模块进行了封装,这样自动化测试框架中的多个测试脚本(py)就可以使用同一个封装后的日志系统,这样各脚本中只需要引用一下即可,方面快捷.那么当我使用unittest框 ...

  3. Python入门之logging日志模块以及多进程日志

    本篇文章主要对 python logging 的介绍加深理解.更主要是 讨论在多进程环境下如何使用logging 来输出日志, 如何安全地切分日志文件. 1. logging日志模块介绍 python ...

  4. python:利用logbook模块管理日志

    日志管理作为软件项目的通用部分,无论是开发还是自动化测试过程中,都显得尤为重要. 最初是打算利用python的logging模块来管理日志的,后来看了些github及其他人的自动化框架设计,做了个比对 ...

  5. Python 中 logging 日志模块在多进程环境下的使用

    因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,Python 中 logging 日志模块在多进程环境下的使用 使用 Pytho ...

  6. Python中logging在多进程环境下打印日志

    因为涉及到进程间互斥与通信问题,因此默认情况下Python中的logging无法在多进程环境下打印日志.但是查询了官方文档可以发现,推荐了一种利用logging.SocketHandler的方案来实现 ...

  7. python的日志模块:logging;django的日志系统;django日志输出时间修改

    Django的log,主要是复用Python标准库中的logging模块,在settings.py中进行配置 源代码 1.__init__.py包含以下类: StreamHandler Formatt ...

  8. python 以单例模式封装logging相关api实现日志打印类

    python 以单例模式封装logging相关api实现日志打印类   by:授客QQ:1033553122 测试环境: Python版本:Python 2.7   实现功能: 支持自由配置,如下lo ...

  9. 0x04 Python logger 支持多进程日志按大小分割

    目录 支持多进程日志按大小分割 多进程日志大小分割handler配置实例 支持多进程日志按大小分割 由于python内置模块logging.handlers.RotatingFileHandler是不 ...

随机推荐

  1. C++ Knowledge series Template & Class

    Function Function is composed of name, parameter (operand, type of operand), return value, body with ...

  2. open ssh 常用的东西

    清除已经存在的但是不同设备的连接信息 ssh-keygen -f "/users/he/.ssh/known_hosts" -R 192.168.1.118 无密码登录openss ...

  3. Visual Studio 编辑器打开项目后,一直提醒Vs在忙,解决方法

    今天打开VS2015后,因为这个解决中有很项目,突然就一直现在加载中,点击VS提示在忙,怎么破那?请往下看 第一种方法 1.关闭VS: 2.去C:\Users\<your users name& ...

  4. Spark核心组件

    Spark核心组件 1.RDD resilient distributed dataset, 弹性分布式数据集.逻辑上的组件,是spark的基本抽象,代表不可变,分区化的元素集合,可以进行并行操作.该 ...

  5. nginx处理HTTP header问题

    在实际开发中遇到http header 自定义key中包含下划线(_)时服务端header丢失的问题,解决办法详细见以下网页内容,感谢原博主 http://blog.csdn.net/dac55300 ...

  6. 数组:获取GET的键名

    1.今天仓鼠遇到这个情况:通过$_GET获取参数,但是参数变成了键名形式 2.那仓鼠想要拿到这个键名,那就要:使用array_keys()获取数组中的所有键名,然后进行转换 代码如下: 结果: 以上 ...

  7. Cygwin Run in the Windows(Simulation of UNIX)

    Preface Environment Cygwin Run in the Windows(Simulation of UNIX) Resource Cygwin Install:http://cyg ...

  8. 实例详解Django的 select_related

    在数据库有外键的时候,使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能.本文通过一个简单的例子详解这两个函数的作用.虽然Q ...

  9. robotframework实战一

    1.环境 1.Robotframework 安装环境,见以下帖子,只要保证python安装成功,安装了python的pip,就可以使用pip一路安装下去了.以下帖子也有基础的操作,帖子路径 http: ...

  10. 【BZOJ4487】[JSOI2015] 染色问题(高维容斥)

    点此看题面 大致题意: 有一个\(n*m\)的矩形,先让你用\(C\)种颜色给它染色.每个格子可染色可不染色,但要求每行每列至少有一个小方格被染色,且每种颜色至少出现一次.求方案数. 高维容斥 显然题 ...