[57.桌面应用开发(5):代码统计器] 零基础学python,简单粗暴

概述

  • 使用【文件操作+GUI+正则表达式】实现对文件夹下代码量的统计
  • 刷代码量神器有木有o( ̄︶ ̄)o

导入依赖

import os
import re
from tkinter import *
from tkinter import filedialog
  • 代码统计器实现
class CodeAnalyzer:
    def __init__(self):

        # 定义排版边距
        marginx = 5
        marginy = 5

        # 窗口和标题
        window = Tk()
        window.title("代码统计器")

        # 使用StringVar对象动态保管打开的文件夹位置
        self.dirPath = StringVar()
        self.dirPath.set("请选择要打开的文件夹")

        # 第一行控件打包在一个面板中
        frame1 = Frame()
        frame1.pack(padx=marginx, pady=(marginy, 0))

        # 打包地址输入框、地址选择按钮在面板1中
        Entry(frame1, width=50, textvariable=self.dirPath).pack(side=LEFT)
        Button(frame1, text="选择文件夹", command=self.openDir).pack(side=LEFT, padx=(marginx, 0))

        # 词频统计按钮
        Button(width=60, text="开始统计", command=self.run).pack(padx=marginx, pady=(marginy, 0))

        # 打包文本域和滚动条在面板2中
        self.retText = Text(width=60, height=20, bg="white")
        self.retText.pack(padx=marginx, pady=(marginy, marginy))

        # 消息循环
        window.mainloop()
        pass

    def openDir(self):
        # 选择要打开的文件夹路径
        self.dirPath.set(filedialog.askdirectory() + "/")

    # 获取文件下的所有py文件,返回py文件列表
    def getPyFilesInDir(self, dirpath):

        # 拿到当前路径下的(一级)文件(含文件夹)列表
        flist = os.listdir(dirpath)

        # 建立Py文件列表
        pyFileList = []

        # 遍历一级子路径
        for name in flist:

            # 获得文件的完整路径
            filepath = dirpath + "/" + name

            # 是文件且是Py文件
            if os.path.isfile(filepath) and name.endswith(".py"):
                pyFileList.append(filepath)

            # 不是Py文件
            elif os.path.isfile(filepath) and not name.endswith(".py"):
                print("%s不是py源代码文件" % (name))

            # 是文件夹
            elif os.path.isdir(filepath):
                # 递归遍历(自己调自身,终止条件为路径没有文件夹),兼并子文件夹的结果
                pyFileList += self.getPyFilesInDir(filepath)

            else:
                print("wtf")

        return pyFileList

    # 以醒目格式打印列表
    def printListClearly(self, mlist):
        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
        for path in mlist:
            print(path)
        print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")

    # 分析单个文件的代码量
    def analyzeCodeFile(self, path):

        # 预定义结果
        totalLines = 0
        commentLines = 0
        blankLines = 0
        effectiveLines = 0

        # 标记当前行是否处于多行注释的内部
        betweenMultipleComment = False

        try:

            # 拿到当前文件代码行数
            file = open(path, "r", encoding="utf-8")
            lineList = file.readlines()
            totalLines = len(lineList)

            # 逐行判断:代码/注释/空行
            for line in lineList:

                # 空行
                if line == "\n":
                    blankLines += 1

                # 判断自结束的多行注释
                # ^\s*'''.*'''\s*$ = 开头+若干空格+'''+若干任意字符+'''+若干空格+结尾
                elif re.match("^\s*'''.*'''\s*$", line):
                    print("%s劳资是自结束多行注释结尾" % (line))
                    commentLines += 1

                    # 标记多行注释结束
                    betweenMultipleComment = False

                # 判断多行注释开头
                # ^\s*''' = 开头+若干空格+'''
                elif re.match("^\s*'''", line) != None and betweenMultipleComment == False:
                    commentLines += 1
                    print("%s劳资是多行注释开头" % (line))

                    # 标记多行注释开始
                    betweenMultipleComment = True

                # 判断多行注释结尾
                # .*'''\s*$ = 若干任意字符+'''+若干空格+结尾
                elif re.match(".*'''\s*$", line) != None and betweenMultipleComment == True:
                    commentLines += 1
                    print("%s劳资是多行注释结尾" % (line))

                    # 标记多行注释结束
                    betweenMultipleComment = False

                # 多行注释内部全部是注释
                elif betweenMultipleComment:
                    commentLines += 1
                    print("%s劳资是多行注释内容" % (line))

                # 单行注释:没有位于多行注释内部,且以#开头
                # ^\s*# = 开头+若干空格+#
                elif betweenMultipleComment == False and re.match(r"^\s*#", line) != None:
                    commentLines += 1
                    print("%s劳资是单行注释" % (line))

                # 其余的都是有效代码
                else:
                    print("%s劳资是单行代码" % (line))
                    effectiveLines += 1
                    pass


            # 打印结果
            print("在文件%s中:" % (path))
            print("totalLines=", totalLines)
            print("commentLines=", commentLines)
            print("blankLines=", blankLines)
            print("effectiveLines=", effectiveLines)

            # 有效代码数对不上账时抛出异常
            # effectiveLines = totalLines - blankLines - commentLines
            if effectiveLines != totalLines - blankLines - commentLines:
                # print("\n\n\n\n\n可疑对象\n\n\n\n\n", path)
                raise RuntimeError("可疑对象:" + path)

            # 关闭文件
            file.close()

            # 返回单个文件的统计结果
            return {
                "totalLines": totalLines,
                "commentLines": commentLines,
                "blankLines": blankLines,
                "effectiveLines": effectiveLines
            }

        # 捕获并处理乱码异常
        except UnicodeDecodeError:
            print("读取%s发生编码错误" % (path))
            pass

    # 执行统计
    def run(self):

        # 遍历文件夹,拿出所有的py文件,返回一个py文件列表
        pyFileList = self.getPyFilesInDir(self.dirPath.get())
        # self.printListClearly(pyFileList)

        # 预定义结果
        totalLines = 0
        commentLines = 0
        blankLines = 0
        effectiveLines = 0

        # 遍历所有的py文件,逐个统计代码量
        for path in pyFileList:
            # 统计单个文件的代码量
            resdict = self.analyzeCodeFile(path)

            # 将单个文件的代码量汇总
            totalLines += resdict["totalLines"]
            commentLines += resdict["commentLines"]
            blankLines += resdict["blankLines"]
            effectiveLines += resdict["effectiveLines"]

        # 显示结果
        self.retText.insert(END, "==================================================" + "\n")
        self.retText.insert(END, "在文件夹%s中共计:" % (self.dirPath.get()) + "\n\n")
        self.retText.insert(END, "源码文件:%d个" % (len(pyFileList)) + "\n")
        self.retText.insert(END, "总代码量:%d" % (totalLines) + "\n")
        self.retText.insert(END, "总注释量:%d,占比%.2f%%" % (commentLines, commentLines * 100 / totalLines) + "\n")
        self.retText.insert(END, "总空行数:%d,占比%.2f%%" % (blankLines, blankLines * 100 / totalLines) + "\n")
        self.retText.insert(END, "有效代码:%d行" % (effectiveLines) + "\n")
        self.retText.insert(END, "==================================================" + "\n")
  • 创建对象
if __name__ == '__main__':
    CodeAnalyzer()
    pass


版权声明:本文为博主原创文章,未经博主允许不得转载。https://my.csdn.net/pangzhaowen
阅读更多
个人分类: python语法
想对作者说点什么? 我来说一句

零基础学Python

2018年03月03日 91.83MB 下载

零基础学python课后题答案

2016年12月28日 8.05MB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭