当前位置: 首页 > 工具软件 > Python plog > 使用案例 >

python 利用logging进行日志输出的技巧

景凌
2023-12-01

写代码用print()函数进行简单调试时,有时候print()写的多了,可能会不知道到底是哪一行代码输出的内容。
当不需要调试时,又得手动的一个个去删除或注释掉print(),这有点麻烦。
于是写了一个利用logging来替代print()的普通输出功能,且曾加了一些输出标记,可以关闭输出,运行计时等一些功能的包printlog (名字就是print和log的组合)。

用法如下:

from printlog import Ptlog        # 导入 printlog
import time

# 参数说明:grade:是否开启“print”功能,stream:是否输出到控制台,tofile:是否输出到本地txt文件。
plog = Ptlog(grade=True, stream=True, tofile=False)    # 实例化一个对象
plog.print("测试计时")    # print 输出

plog.start()    		  # 开始计时

time.sleep(2)
plog.pause()              # 计时暂停
time.sleep(2)

plog.start()              # 继续计时
time.sleep(1)
plog.stop()              # 停止计时。

plog.print(plog.time)    # plog.time 读取耗时的浮点型。

运行结果:

test.py [2020-05-11 23:40:59,477] 信息提示 (INFO-20):     # 这行是自动显示的附加信息,test.py 为python文件名,后面为这行代码运行的时间。
[6行]:测试计时                                           # [6行] 表示test.py 文件中的第6行。

test.py [2020-05-11 23:40:59,477] 信息提示 (INFO-20): 
[8行]:计时开始

test.py [2020-05-11 23:41:01,478] 信息提示 (INFO-20): 
[11行]:计时暂停,当前累计运行时长为:2.00019秒。

test.py [2020-05-11 23:41:03,478] 信息提示 (INFO-20): 
[14行]:继续计时...

test.py [2020-05-11 23:41:04,478] 信息提示 (INFO-20): 
[16行]:计时停止,最终运行时长为:3.00075秒。

test.py [2020-05-11 23:41:04,478] 信息提示 (INFO-20): 
[18行]:3.0007485999999997

下面是这个包的完整代码:

from time import perf_counter, localtime, sleep
import logging
from functools import partial


class Ptlog:
    """ 一个利用 logging 模块,来进行输出,和计时的模块。
        参数和方法说明:
       grade=True,             开启/关闭功能,默认 True 显示。
       stream=True,            设置是否输出到控制台。
       tofile=False            设置是否写入到文件。
       Ptlog.print(content)    类似print输出, 参数 content 为输出内容.
       Ptlog.start()           开始计时,
       Ptlog.pause()           暂停计时,使用start可重新开始
       Ptlog.stop()            停止计时,计时清零,
       Ptlog.time              读取累计的时间(浮点型)"""
    def __init__(self, grade=True, stream=True, tofile=False):
        self.grade = grade
        self.stream = stream
        self.tofile = tofile
        self.init_log()
        self.time_start = 0      # 用来标记每次开始时的 perf_counter
        self._sum_time = 0
        self.time_flg = True
        self.time = 0

    def init_log(self):
        log_format = '{filename} [{asctime}] {name} ({levelname}-{levelno}): ' \
                     '\n[{lineno}行]:{message}\n'
        # logging.basicConfig(level=self.grade, format=log_format, style='{')

        self.pt_log = logging.getLogger('信息提示')
        if self.grade:
            self.pt_log.setLevel(20)
            if self.stream:
                shandler = logging.StreamHandler()
                shandler.setFormatter(logging.Formatter(log_format, style='{'))
                self.pt_log.addHandler(shandler)

            if self.tofile:
                now_time = localtime()
                file_name = f'{now_time.tm_year}年{now_time.tm_mon:02}月{now_time.tm_mday:02}日' \
                            f'-{now_time.tm_hour:02}时{now_time.tm_min:02}分{now_time.tm_sec:02}秒'
                fhandler = logging.FileHandler(f'{file_name}.txt', mode='a', encoding='utf-8')
                fhandler.setFormatter(logging.Formatter(log_format, style='{'))
                self.pt_log.addHandler(fhandler)
        else:
            self.pt_log.setLevel(50)


    @property
    def print(self):
        return self.pt_log.info

    @property
    def start(self):
        if self.time_flg:              # 为真时,可以开始计时。
            if self._sum_time == 0:    # 判断是否是新开始的计时,还是暂停后重新开始的计时。
                content = "计时开始"
            else:
                content = "继续计时..."
            self.time_start = perf_counter()
            self.time_flg = False      # 设为假,说明正处于计时中,不能再次开始计时。
            pp = partial(self.pt_log.info, content)
        else:
            content = "警告!!! 正在计时中,无需重复开始。使用 pause 或 stop 方法后,可再次使用start方法。"
            pp = partial(self.pt_log.warning, content)
        return pp

    @property
    def pause(self):
        if not self.time_flg:   # 如果处于计时中
            self._sum_time = perf_counter() - self.time_start + self._sum_time
            self.time_flg = True
            content = f"计时暂停,当前累计运行时长为:{self._sum_time:.5f}秒。"
            pp = partial(self.pt_log.info, content)
            self.time = self._sum_time                # 一个可以外部读取时间的属性。
        else:
            content = "警告!!! 计时还未开始,请先使用start方法。"
            pp = partial(self.pt_log.warning, content)
        return pp

    @property
    def stop(self):
        if not self.time_flg:          # 如果正处于计时中,停止计时,返回累计时间。
            self._sum_time = perf_counter() - self.time_start + self._sum_time
            self.time_flg = True
            content = f"计时停止,最终运行时长为:{self._sum_time:.5f}秒。"
            self.time = self._sum_time
            self._sum_time = 0          # 初始化累计的时间值。
            self.time_start = 0         # 初始化开始的 perf_counter()
            pp = partial(self.pt_log.info, content)
        elif self.time_flg and self._sum_time > 0:     # 如果处于暂停中,直接停止计时,返回累计时间。
            content = f"计时停止,最终运行时长为:{self._sum_time:.5f}秒。"
            self.time = self._sum_time
            self._sum_time = 0
            self.time_start = 0
            pp = partial(self.pt_log.info, content)
        else:
            content = "警告:计时还未开始,请先使用start方法。"
            pp = partial(self.pt_log.warning, content)
        return pp
 类似资料: