美文网首页Python
python多进程写日志解决方案

python多进程写日志解决方案

作者: PyKailyn | 来源:发表于2016-11-17 13:53 被阅读0次

    通常,我们的日志是这样写的:

    _code_log_file = os.path.join(BASE_DIR, 'logs', 'code.log')
    _code_log_handler = TimedRotatingFileHandler(_code_log_file, when="D")
    _code_log_formatter = logging.Formatter('%(levelname)s %(pathname)s->func:%(funcName)s line:%(lineno)d %(message)s %(asctime)s')
    _code_log_handler.setFormatter(_code_log_formatter)# 此处设置logger名称,否则默认的会和tornado的logger相同而使得下方设置的错误等级被轻质更新为info
    code_log = logging.getLogger('code-log')
    code_log.setLevel(logging.INFO)
    code_log.addHandler(_code_log_handler)
    

    这样写,一般情况下不会有问题,即使程序中使用了多线程写日志也不会导致日志丢失。(logging是线程安全的)

    但是,实际项目中,为了最大量的利用CPU,我们需要启动多个python进程,这个时候,这样写日志就会出问题了。当有多个进程同时写同一个日志文件时,就会出现覆盖而导致日志信息丢失的问题。

    对于这样的问题,通常有两种方案:

    一. 为每个进程分配不同的文件
    原理:规避了多个进程写同一个文件的情境。问题自然解决。
    优点:不用写额外代码或第三方包的引用。
    缺点:日志分散,不利于日志查看和监测。

    二. 重写handler,用方法解决多进程写文件的问题
    原理:就像同一时间多个客户买火车票的问题一样,加入锁机制。
    优点:日志集中,方便查看与监测。
    缺点:需要自行解决锁的相关算法或引入第三方包。

    多进程写日志的第三方包ConcurrentLogHandler
    详细介绍:https://pypi.python.org/pypi/ConcurrentLogHandler/0.9.1
    具体使用如下:

    _code_log_file = os.path.join(BASE_DIR, 'logs', 'code.log')
    # 对应三个参数为:文件名,写入模式(a表示追加),文件大小(2M),最多保存5个文件
    _code_log_handler = ConcurrentRotatingFileHandler(_code_log_file, "a", 2*1024*1024, 5)
    _code_log_formatter = logging.Formatter('%(levelname)s %(pathname)s->func:%(funcName)s '
                                            'line:%(lineno)d %(message)s %(asctime)s')
    _code_log_handler.setFormatter(_code_log_formatter)
    # 此处设置logger名称,否则默认的会和tornado的logger相同而使得下方设置的错误等级被轻质更新为info
    code_log = logging.getLogger('code-log')
    code_log.setLevel(logging.INFO)
    code_log.addHandler(_code_log_handler)
    
    code_log.info("balabala")
    

    在windows上使用ConcurrentLogHandler的问题
    暂不知什么原因,windows上使用该handler会出错,程序卡死在写日志的地方。调试跟踪到该Handler内部,是某个锁的问题。但该问题在正式环境Linux中不会存在,也没去深究。临时的解决方法是在日志初始化的地方判断当前系统,是windows则使用传统的日志handler。
    代码如下:

    
    import logging
    from setting import BASE_DIR
    import os
    from cloghandler import ConcurrentRotatingFileHandler as LogHandler
    import platform
    import json
    
    
    # 不知道为毛windows上ConcurrentRotatingFileHandler这个handler会有导致程序卡死,linux上无问题
    # 暂时采用这种方法解决windows上因卡死导致的调试不方便问题
    if str(platform.system()) == "Windows":
        from logging.handlers import RotatingFileHandler as LogHandler
    
    
    # -------------------------------运行日志(代码运行记录)-------------------------------
    _code_log_file = os.path.join(BASE_DIR, 'logs', 'code.log')
    
    _code_log_handler = LogHandler(_code_log_file, "a", 20*1024*1024, 50)
    _code_log_formatter = logging.Formatter('%(levelname)s %(pathname)s->func:%(funcName)s '
                                            'line:%(lineno)d %(message)s %(asctime)s')
    _code_log_handler.setFormatter(_code_log_formatter)
    # 此处设置logger名称,否则默认的会和tornado的logger相同而使得下方设置的错误等级被更新为info
    code_log = logging.getLogger('code-log')
    code_log.setLevel(logging.INFO)
    code_log.addHandler(_code_log_handler)
    

    更新

    1. 用concurrent-log-handler替换ConcurrentLogHandler可解决windows因锁机制导致的卡死问题。即pip install ConcurrentLogHandler 改为pip install concurrent-log-handler.

    相关文章

      网友评论

        本文标题:python多进程写日志解决方案

        本文链接:https://www.haomeiwen.com/subject/rpcwuttx.html