python日志打印和写入并发简易版本实现

大家一般都用logging日志打印,但logging是线程安全的,多进程也有很多介绍,引入一些文件锁,对logging做好配置,能过支持。

但通过测试,发现多进程时还是容易出现重复写入文件或者打印正常漏写入文件的问题。

我的日志需求比较简单,能够区分文件,正确的写入日志文件。

引入文件锁;日志写入函数封装到一个操作_Logger类中; 日志名称和写入级别封装到一个业务类Logger中。

本范例基于python3实现。本范例20个进程并发,分别写入3个文件,每s每个文件写入超过100行数据,日志文件中没有数据冗余,也没有数据遗漏。

# -*-coding:utf-8-*- """Author:yinshunyaoDate:2017/3/5 0005下午 10:50"""# import loggingimport osimport time# 利用第三方系统锁实现文件锁定和解锁if os.name == ‘nt‘:    import win32con, win32file, pywintypes    LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK    LOCK_SH = 0  # The default value    LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY    __overlapped = pywintypes.OVERLAPPED()

def lock(file, flags):        hfile = win32file._get_osfhandle(file.fileno())        win32file.LockFileEx(hfile, flags, 0, 0xffff0000, __overlapped)

def unlock(file):        hfile = win32file._get_osfhandle(file.fileno())        win32file.UnlockFileEx(hfile, 0, 0xffff0000, __overlapped)

elif os.name == ‘posix‘:    from fcntl import LOCK_EX

def lock(file, flags):        fcntl.flock(file.fileno(), flags)

def unlock(file):        fcntl.flock(file.fileno(), fcntl.LOCK_UN)else:    raise RuntimeError("File Locker only support NT and Posix platforms!")
 

class _Logger:    file_path = ‘‘
    #初始化日志路径

@staticmethod    def init():

if not _Logger.file_path:            _Logger.file_path = ‘%s/Log‘ % os.path.abspath(os.path.dirname(__file__))        return True

@staticmethod    def _write(messge, file_name):        if not messge:            return True        messge = messge.replace(‘\t‘, ‘,‘)        file = ‘{}/{}‘.format(_Logger.file_path, file_name)        while True:            try:                f = open(file, ‘a+‘)                lock(f, LOCK_EX)                break            except:                time.sleep(0.01)                continue

# 确保缓冲区内容写入到文件        while True:            try:                f.write(messge + ‘\n‘)                f.flush()                break            except:                time.sleep(0.01)                continue

while True:            try:                unlock(f)                f.close()                return True            except:                time.sleep(0.01)                continue    
    @staticmethod    def write(message, file_name, only_print=False):        if not _Logger.init(): return        print(message)        if not only_print:            _Logger._write(message, file_name)

class Logger:    def __init__(self, logger_name, file_name=‘‘):        self.logger_name = logger_name        self.file_name = file_name
    # 根据消息级别,自定义格式,生成消息

def _build_message(self, message, level):        try:            return ‘[%s]\t[%5s]\t[%8s]\t%s‘ \                   % (time.strftime(‘%Y-%m-%d %H:%M:%S‘), level, self.logger_name, message)        except Exception as e:            print(‘解析日志消息异常:{}‘.format(e))            return ‘‘

def warning(self, message):        _Logger.write(self._build_message(message, ‘WARN‘), self.file_name)

def warn(self, message):        _Logger.write(self._build_message(message, ‘WARN‘), self.file_name)

def error(self, message):        _Logger.write(self._build_message(message, ‘ERROR‘), self.file_name)

def info(self, message):        _Logger.write(self._build_message(message, ‘INFO‘), self.file_name, True)

def debug(self, message):        _Logger.write(self._build_message(message, ‘DEBUG‘), self.file_name)
 
# 循环打印日志测试函数

def _print_test(count):    logger = Logger(logger_name=‘test{}‘.format(count), file_name=‘test{}‘.format(count % 3))    key = 0    while True:        key += 1        # print(‘{}-{}‘.format(logger, key))        logger.debug(‘%d‘ % key)        logger.error(‘%d‘ % key)

if __name__ == ‘__main__‘:    from multiprocessing import Pool, freeze_support    freeze_support()
    # 进程池进行测试    pool = Pool(processes=20)    count = 0    while count < 20:        count += 1        pool.apply_async(func=_print_test, args=(count,))    else:        pool.close()        pool.join()
 
时间: 2024-10-13 00:20:45

python日志打印和写入并发简易版本实现的相关文章

Python 日志打印模块

1 logging模块简介 logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级.日志保存路径.日志文件回滚等:相比print,具备如下优点: 可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息: print将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据:logging则可以由开发者决定将信息输出到什么地方,以及怎么输出: 2 logging模块使用 2.1 基本使用 配置logging基本的设

Python日志打印

简单示例 import sys import ctypes import logging import logging.handlers reload(sys) sys.setdefaultencoding('utf-8') LOG_FILE = 'test_log' logging.basicConfig( filename = LOG_FILE, format = '%(asctime)s - %(levelname)s -%(process)d- %(filename)s:%(funcNa

python日志,支持彩色打印和文件大小切片写入和写入mongodb

支持不同logger name的日志写入不同的文件,不同logger name日志写入不同的mongodb 的collection.LogManager比较容易调用,因为里面的内部方法全都使用了下划线,使用了下划线的就是保护和私有方法不需要外界调用,也不需要看懂他,在调用时候pycharm不会自动补全提示这些带下划线的无关方法了,只暴露了get_and_add_handlers和get_without_handlers两个可能需要调用的方法,pyrcharm可以自动补全这两个方法. 主要思路和模

Python+request 分模块存放接口,多接口共用参数URL、headers的抽离,添加日志打印等《三》

主要介绍内容如下: 1.分模块存放接口 2.多接口共用参数URL.headers的抽离为配置文件 3.添加日志打印 4.一个py文件运行所有所测的接口 如上介绍内容的作用: 1.分模块存放接口:方便多人协作,对模块接口的分开存放,方便后期新增模块接口的录入,也方便接口出现报错后,定位模块 2.多接口共用参数URL.headers的抽离为配置文件: (1)URL:单独进行配置文件中的修改,主要是方便后期接口域名出现变化,方便更改,示例,本次URL前缀为:https://127.0.0.1,下次开发

调用百度ocr的API,python简易版本

调用百度ocr的API,python简易版本 https://www.jianshu.com/p/e10dc43c38d0 1. 注册 百度云注册账号 https://cloud.baidu.com/?from=console 管理应用 https://console.bce.baidu.com/ai/#/ai/ocr/overview/index 创建一个 图1登陆之后的界面 进入链接之后创建应用,由于是从文字识别点进去的,所以默认选中的就是ocr相关内容,填好表格确认. 图2 创建应用之后的

python日志设置[logging]

logging介绍 用于输出运行日志,可以设置输出日志的等级.日志保存路径.日志文件回滚等; 优点: 可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息: 可以由开发者决定将信息输出到什么地方,以及怎么输出(print将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据) 日志级别 DEBUG:最详细的日志信息,典型应用场景是 问题诊断 INFO:信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工

python日志模块-logging

日志模块 logging logging模块主要可以根据自定义日志信息,在程序运行的时候将日志打印在终端及记录日志到文件中.在这先了解一下logging支持的日志五个级别 debug() 调试级别,一般用于记录程序运行的详细信息 info() 事件级别,一般用于记录程序的运行过程 warnning() 警告级别,,一般用于记录程序出现潜在错误的情形 error() 错误级别,一般用于记录程序出现错误,但不影响整体运行 critical 严重错误级别 , 出现该错误已经影响到整体运行 简单用法,将

Python 日志工具(logging) 基础教程

什么是 logging ? 日志是跟踪软件运行时发生的事件,软件的开发人员可以通过日志快速的定位问题的位置.事件也分重要性即事件的严重程度. 什么时候使用日志? logging 提供了一组方便操作日志记录的功能,这些是 debug(), info(),warning(),error(),critical(). 通过想要执行的任务确定使用日志记录的方法. 你想要执行的任务 日志记录的最佳方法 一个脚本或程序显示在终端上 print() 程序正常运行过程中发生的事件 logging.info() o

SpringBoot2.0 基础案例(02):配置Log4j2,实现不同环境日志打印

一.Log4j2日志简介 日志打印是了解Web项目运行的最直接方式,所以在项目开发中是需要首先搭建好的环境. 1.Log4j2特点 1)核心特点 相比与其他的日志系统,log4j2丢数据这种情况少:disruptor技术,在多线程环境下,性能高:并发的特性,减少了死锁的发生. 2)性能测试 2.日志打印之外观模式 每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,增加应用程序代码和日志框架的耦合性. <阿里巴巴Java开发手册>,其中有一条规范做了『强制』要求: SL