鱼C论坛

 找回密码
 立即注册
查看: 2109|回复: 0

[作品展示] 一个给代码运行计时的模块

[复制链接]
发表于 2022-12-3 18:39:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
原本想给自己的代码辅助用的(用于知道挂机运行很久后,代码运行到哪了),但因为后面没有需要运行那么长时间的代码而就没用这个模块了,所以就分享出来 ,也当做自己的一个云备份

'''
为代码添加个建议的实显信息条
可在一个运行时间很长的程序中 ,有个看得见的期望(相当于红绿灯中有了读秒)

导入方法:
    from infoBar import infoBar #infoBar是这个模块的名

启用示例:
    @infoBar
    def func():
        ...

    或↓
    with infoBar:
        ...

具体修改演示:
    参考if __name__ == '__main__':里的__useExample()
'''
from time import perf_counter as _perf_counter ,sleep as _sleep
from datetime import timedelta as _timedelta
from concurrent.futures import ThreadPoolExecutor as _ThreadPoolExecutor
from functools import wraps as _wraps


class _InfoBar:
    def __init__(self):
        # region 基础配置
        self.__enterNum = 0
        self.__refreshTime = 0.1
        self.__executor = _ThreadPoolExecutor(1)
        # endregion

        # region 一个简单就能实现的功能 ,可以让用户记录func内想知道的一些信息(将知道的信息带出来)
        self.shelve = {}
        # endregion

        # region 信息栏配置
        # region 信息数据
        self.__startTime = 0
        self.__defaultTitle = ''
        self.__title = self.__defaultTitle
        self.__defaultMsg = ''
        self.__msg = self.__defaultMsg
        self.__progressCur = 0
        self.__progressMax = 0
        # endregion

        self.__barFormat = '[{Time}]{title}{progress}:{msg}'

        self.__barValueDict = {
            'Time': lambda: f'{_timedelta(seconds=int(_perf_counter() - self.__startTime))}' ,
            'title': lambda: f'{self.__title}' ,
            'progress': lambda: f'({self.__progressCur / self.__progressMax:.2%})'
            if self.__progressMax else '' ,
            'msg': lambda: f'{self.__msg}' ,
        }
        # endregion

    def __del__(self):
        self.__executor.shutdown()

    def __enter__(self):
        self.__enterNum += 1
        if self.__enterNum == 1:
            self.__startTime = _perf_counter()
            # region 清空之前使用数据
            self.startSet()
            self.shelve.clear()
            # endregion
            self.__executor.submit(self.__timing)
        return self

    def __exit__(self ,exc_type ,exc_val ,exc_tb):
        self.__enterNum -= 1
        if self.__enterNum == 0:
            if exc_val is None:
                print(f'{self}\n' ,end='')

    def __call__(self ,func):
        @_wraps(func)
        def call(*args ,**kwargs):
            with self:
                return func(*args ,**kwargs)

        return call

    def __str__(self):
        text = self.__barFormat.format_map(
            {
                k: self.__barValueDict[k]()
                for k in self.__barValueDict
                if k in self.__barFormat
            }
        )
        if len(text) > 100:
            text = text[:101] + '...'
        return text

    def __timing(self):
        while self.__enterNum:
            print(f'{self}\r' ,end='')
            _sleep(self.__refreshTime)

    def startSet(self ,defaultTitle: str = '' ,defaultMsg: str = '' ,refreshTime: int = 0.1):
        '''
        设置new的默认title和msg \n
        一般只在开头调用一次 ,要来描述最初情况下 ,这段func在做什么\n
        :param defaultTitle: 此func里默认的title值 ,用来描述这个函数最初情况下在做什么
        :param defaultMsg: 此func里默认的msg值 ,用来描述这个函数最初情况下所想知道的信息 ,一般不设置
        :param refreshTime: 设置刷新时间 ,一般不设置
        :return:
        '''
        if self.__enterNum == 1:
            self.__defaultTitle = defaultTitle
            self.__defaultMsg = defaultMsg
            self.__refreshTime = refreshTime
            self.new()

    def new(self ,title: str = ... ,msg: str = ... ,setPMax: int = 0 ,setPCur: int = 0):
        '''
        覆盖infoBar的实显信息\n
        注意:\n
        别企图用new直接代替chg \n
        因为那样会在使用进度百分比值时极大幅度拖累运行速度\n
        :param title: 设置初始"大概在做的事"的描述
        :param msg: 设置初始"具体关注的信息"
        :param setPMax: 设置初始"进度百分比"的分母值
        :param setPCur: 设置初始"进度百分比"的分子值,一般不设置
        :return:
        '''
        if self.__enterNum == 1:
            self.__title = self.__defaultTitle if title is ... else title
            self.__msg = self.__defaultMsg if msg is ... else msg
            self.__progressMax = setPMax
            self.__progressCur = setPCur
            print(f'{self}\r' ,end='')

    def msg(self ,msg: str = ... ,addPCur: int = 1 ,title: str = ...):
        '''
        修改infoBar的时显信息\n
        :param msg: 修改"具体关注的信息"
        :param addPCur: 在设置了(使用了)"进度百分比"时 ,增加其分子值
        :param title: 修改"当前在做的事" ,一般不修改
        :return:
        '''
        if self.__enterNum == 1:
            if msg is not ...: self.__msg = msg
            if self.__progressMax:
                self.__progressCur += addPCur
            if title is not ...: self.__title = title

    def pop(self ,title: str = ... ,msg: str = ...):
        '''
        弹出你所想要修改后记录的信息 \n
        如果没有记录这弹出的需求 \n
        则可以直接用new的方法代替 \n
        :param title: 修改"大概在做的事"的描述
        :param msg: 修改"具体关注的信息"
        :return:
        '''
        if self.__enterNum == 1:
            if title is not ...: self.__title = title
            if msg is not ...: self.__msg = msg
            print(f'{self}\n' ,end='')
            self.new()


infoBar = _InfoBar()
__all__ = [
    'infoBar'
]
if __name__ == '__main__':
    @infoBar
    def __useExample(arg1=10000000):
        infoBar.startSet('这里是使用示例')  # 在开头设置new是title和msg的默认值 ,来说明整个func在最初做什么
        _sleep(2)
        infoBar.new('for i in arg1中' ,'' ,arg1)  # 设置新的信息条来覆盖旧的信息条(没有设置的则为空)
        for item in range(arg1):
            infoBar.msg(f'修改需要注意的信息,如item的值:{item}')  # 随着程序的运行 ,而修改你所需要关注的信息
        infoBar.pop('for i in arg1结束' ,f'记录出想要记录的信息例如item的值是{item}')  # 在结束时 ,弹出你记录的完成结果
        _sleep(2)
        infoBar.new('测试结束' ,f'返回值是(arg1):{arg1}')  # 可以在最后设置默认信息 ,在不同的结束能得知不同的情况
        return arg1


    # __useExample()

    # region 这里等于__useExample里的代码用with来运行
    with infoBar:
        arg1 = 10000000
        infoBar.startSet('这里是使用示例')  # 在开头设置new是title和msg的默认值 ,来说明整个func在最初做什么
        _sleep(2)
        infoBar.new('for循环中' ,'' ,arg1)  # 设置新的信息条来覆盖旧的信息条(没有设置的则为空)
        for item in range(arg1):
            infoBar.msg(f'修改需要注意的信息,如item的值:{item}')  # 随着程序的运行 ,而修改你所需要关注的信息
        infoBar.pop('for i in arg1结束' ,f'记录出想要记录的信息例如item的值是{item}')  # 在结束时 ,弹出你记录的完成结果
        _sleep(2)
        infoBar.new('测试结束' ,f'返回值是(arg1):{arg1}')  # 可以在最后设置默认信息 ,在不同的结束能得知不同的情况
    # endregion

    pass
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-15 18:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表