写代码用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