图形界面多进程代码统计工具

import os
import chardet
import tkinter as tk
import multiprocessing
import time


# 统计指定目录下的代码文件,并添加至队列中
def find_all_file(queue, path, file_type=None):
    # 判断需要统计的文件类型
    if file_type is None:
        file_type = [".py",".cpp",".java",".c",".h",".php",".asp"]
    # 若传入的为单个文件
    if os.path.isfile(path):
        if os.path.splitext(path)[1] in file_type:
            queue.put(path)
        else:
            return "文件格式有误"
    else:
        for root, dirs, files in os.walk(path):
            for file in files:
                if os.path.splitext(file)[1] in file_type:
                    queue.put(os.path.join(root, file))
    return queue


# 使用多进程统计队列中的代码总行数
def all_file_code_count(queue, path, file_type=None):
    start = time.time()
    queue = find_all_file(queue, path, file_type)
    # 有效文件数
    total_file_count = queue.qsize()
    # 有效代码行数
    total_line_count = multiprocessing.Value("i", 0)
    # 总注释数
    total_annotation_count = multiprocessing.Value("i", 0)
    # 总空行数
    total_blank_count = multiprocessing.Value("i", 0)
    # 获取当前计算机的cpu核数
    cpu_num = multiprocessing.cpu_count()
    p_list = [multiprocessing.Process(target=single_file_code_count, \
        args=(queue, total_line_count, total_annotation_count, total_blank_count)) for i in range(cpu_num)]
    for p in p_list:
        p.start()
        p.join()
    end = time.time()
    return total_file_count, total_line_count.value, total_annotation_count.value, total_blank_count.value, end-start


# 统计单个文件的代码行数
def single_file_code_count(queue, total_line_count, total_annotation_count, total_blank_count):
    while not queue.empty():
        file_path = queue.get()
        # 是否多行注释的标识
        flag = False
        if not os.path.exists(file_path):
            return "file doesn't exist"
        else:
            # 首先获取文件的编码
            with open(file_path, "rb") as f:
                content = f.read()
            file_chardet = chardet.detect(content)["encoding"]
            f = open(file_path, encoding=file_chardet)
            for line in f:
                # 多行注释的处理
                if line.strip().startswith("'''") or line.strip().startswith('"""') or \
                        line.strip().endswith("'''") or line.strip().endswith('"""'):
                    if flag == True:
                        flag = False
                    else:
                        flag = True
                    total_annotation_count.value += 1
                elif line.strip().startswith("/*"):
                    flag = True
                elif line.strip().endswith("*/"):
                    flag = False
                else:
                    # 跳出多行注释才进行判断记录
                    if not flag:
                        # 空行不记录
                        if line.strip() == "":
                            total_blank_count.value += 1
                            continue
                        # 单行注释需要区分是否文件编码声明
                        elif line.strip().startswith("#") or line.strip().startswith("//"):
                            # 编码声明行
                            if line.strip().startswith("#encoding") or line.strip().startswith("#coding") \
                                    or line.strip().startswith("#-*-"):
                                total_line_count.value += 1
                            # 单行注释行
                            else:
                                total_annotation_count.value += 1
                        # 其余情况则为真正代码行
                        else:
                            total_line_count.value += 1
                    # 仍在多行注释内
                    else:
                        total_annotation_count.value += 1
            f.close()
            return total_line_count, total_annotation_count, total_blank_count


# GUI:图形化代码统计工具
def gui(queue, file_type=None):

    # 创建主窗口
    window = tk.Tk()

    # 设置主窗口标题
    window.title("代码统计工具")
    # 设置主窗口大小(长*宽)
    window.geometry("500x300")  # 小写x

    ## Label部件:界面提示语
    # 在主窗口上设置标签(显示文本)
    l = tk.Label(window, text="请输入需要统计的目录或文件:")
    # 放置标签
    l.pack()  # Label内容content区域放置位置,自动调节尺寸


    ## Entry部件:单行文本输入
    e = tk.Entry(window, bd=5, width=50)
    e.pack()

    ## 定义Button事件的处理函数
    def button_click():
        # 获取输入框的目录路径
        path = e.get()
        # 调用代码统计工具
        res = all_file_code_count(queue, path, file_type)
        # 若返回的是异常结果
        if isinstance(res, str):
            # 使用configure实现实时刷新数据
            l2.configure(text=res)
        # 返回正常结果
        else:
            file_count = res[0]
            line_count = res[1]
            annotation_count = res[2]
            blank_count = res[3]
            time_need = res[4]
            l2.configure(text="文件总数:%s\n代码行总数:%s\n注释行总数:%s\n空行总数:%s\n总耗时:%s秒\n"\
                % (file_count, line_count, annotation_count, blank_count, round(time_need, 2)))

    ## Button部件:按钮
    b = tk.Button(window, text="提交", command=button_click)
    b.pack()

    # 用于显示统计结果
    l2 = tk.Label(window, text="", width=200, height=10)
    l2.pack()

    # 主窗口循环显示
    window.mainloop()
    '''
    注意:因为loop是循环的意思,window.mainloop就会让window不断的刷新。
    如果没有mainloop,就是一个静态的window,传入进去的值就不会有循环。
    mainloop就相当于一个很大的while循环,有个while,每点击一次就会更新一次,所以我们必须要有循环。
    所有的窗口文件都必须有类似的mainloop函数,mainloop是窗口文件的关键的关键。
    '''


if __name__ == "__main__":
    queue = multiprocessing.Queue()
    gui(queue) 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值