最近,公司领导突然想起来要看每日业务量统计报告,还好之前一位同事写过一个python脚本,通过扫描系统日志文件分类统计不同业务的数量,整个脚本有如下两个配置信息:
cmd_cfg = { "cmd_A_1" :"业务A_1", "cmd_A_2" :"业务A_2", ... ... "cmd_B_1" :"业务B_1", "cmd_B_2" :"业务B_2", ... ... }
cmd_A = ["cmd_A_1", "cmd_A_2", ...] cmd_B = ["cmd_B_1", "cmd_B_2", ...] |
整个脚本的逻辑是在日志文件中逐个命令数组搜索每个命令组中的命令,统计每个命令出现的次数及在整个命令组中的占比量,最后,以中文名称输出上述每组命令的统计值及命令组的名称。
for cmd in cmd_A: #count cmd in log #print cmd_cfg[cmd], count #sum of count print cmd_A sum for cmd in cmd_B: #count cmd in log #print cmd_cfg[cmd], count #sum of count print cmd_B sum … … |
上面的代码一眼看去,就会看到大量明显重复的代码,其主要差别无非最后输出的命令组的名称不同而已。此外,一个更重要的问题是每个命令的中文名称配置在一个独立的字典结构里面,这样每当有新的命令加进来的时候,中文名称配置文件和命令数组就需要同步修改,给整个脚本的可扩展性带来很大的不方便。
首先的重构,是把原来的‘cmd_cfg’中的中文名称映射,分散到每个命令数组中,把命令数组变更为命令字典,这样对于原来命令数组的遍历,无非变为对每个命令字典的keys的遍历。这样,就不再需要单独的命令中文名称配置文件,以后有新的命令加入时,只需要按照业务分类加入相应的命令字典即可。
cmd_A = { "cmd_A_1":"业务A_1", "cmd_A_2":"业务A_2", ... ... } cmd_B = { "cmd_B_1":"业务B_1", "cmd_B_2":"业务B_2", ... } for cmd, name in cmd_A.items(): #count cmd in log #print name, count #sum of count print cmd_A sum for cmd, name in cmd_B.items(): #count cmd in log #print name, count #sum of count print cmd_B sum … … |
第一步的重构,解决了命令中文名称配置分散的问题,但仍有大量的重复的几乎完全一样的for循环存在。前面已经说过,每个for循环的差异无非最后要输出的命令组的名字,我想到的一个办法是把这个名字也放到各个命令字典里面去,给这个名字设置一个特殊的key值,最后在需要输出命令组名字的时候,用这个特殊的key到相应的命令字典获取即可。
cmd_A = { "group_name":"cmd_A", "cmd_A_1":"业务A_1", "cmd_A_2":"业务A_2", ... ... } cmd_B = { "group_name":"cmd_B", "cmd_B_1":"业务B_1", "cmd_B_2":"业务B_2", ... ... } for cmd, name in cmd_A.items(): #count cmd in log #print name, count #sum of count print cmd_A[“group_name”] sum for cmd, name in cmd_B.items(): #count cmd in log #print name, count #sum of count print cmd_B[“group_name”] sum … … |
从上面的代码可以看出,不仅每个for循环的结构完全一样,最后输出名字组名字的操作也是一样的,因而,可以进一步优化,把所有的命令字典组成一个大的数组,用一个外层的for循环遍历这个大数组,内部的一层for循环则与原来的for循环逻辑一样。
groups = [cmd_A, cmd_B, ……] for grp in groups: for cmd, name in cmd_A.items(): #count cmd in log #print name, count #sum of count print grp[“group_name”] sum … … |
最后,经过上述三步重构,不仅废弃了冗余的命令中文名称配置文件,还将原来的十几个几乎完全一样的for循环,简化为一个for循环。这样,不仅代码更精炼,为后续的命令扩展也提供了很大的便利:某个命令组新增命令只需要修改相应的命令字典;新增命令组时,则只需要扩展‘groups’数组即可。