如何写代码行数统计脚本

wen 实用脚本 22

从基础到高级实践指南

目录导读

  1. 为什么需要代码行数统计脚本?
  2. 基础实现:用Shell命令统计代码行数
  3. 进阶方案:Python脚本实现智能统计
  4. 处理边缘情况:忽略注释与空行
  5. 性能优化:处理大型代码库
  6. 常见问题问答(FAQ)

为什么需要代码行数统计脚本?

在项目管理、代码审查或技术汇报时,统计代码行数是常见需求,一个可靠的代码行数统计脚本能自动排除注释、空行和特定文件,生成准确数据,许多开发者曾遇到这样的问题:手动统计上千个文件既耗时又容易出错——这正是我们写脚本的动力。

如何写代码行数统计脚本

核心目标:快速统计“有效代码行数”,即去除注释、空行、格式化括号后的代码净行数。


基础实现:用Shell命令统计代码行数

最简单的方案是使用Linux/Unix的wc(word count)命令组合find来递归统计:

find . -name "*.py" -exec cat {} \; | wc -l

这条命令会统计当前目录下所有.py文件的总行数,但它的缺陷很明显:包含空行和注释

改进版:用grep -v过滤空行和注释:

find . -name "*.py" | xargs grep -v -e '^\s*$' -e '^\s*#' | wc -l

注意:这种方式在处理多行注释时仍有局限。


进阶方案:Python脚本实现智能统计

Python因其正则表达式和文件处理能力,是编写行数统计脚本的理想语言,以下是一个能分别统计总行数、代码行、注释行、空行的脚本示例:

import os
import re
def count_lines_in_file(file_path):
    total_lines = 0
    code_lines = 0
    comment_lines = 0
    blank_lines = 0
    with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
        for line in f:
            total_lines += 1
            stripped = line.strip()
            if not stripped:
                blank_lines += 1
            elif stripped.startswith('#'):  # 单行注释
                comment_lines += 1
            else:
                code_lines += 1
    return total_lines, code_lines, comment_lines, blank_lines
def traverse_directory(root_dir, extensions=None):
    if extensions is None:
        extensions = ['.py', '.java', '.js', '.ts', '.c', '.cpp']
    summary = {'total':0, 'code':0, 'comment':0, 'blank':0}
    for root, dirs, files in os.walk(root_dir):
        for file in files:
            ext = os.path.splitext(file)[1].lower()
            if ext in extensions:
                path = os.path.join(root, file)
                try:
                    t, c, cm, b = count_lines_in_file(path)
                    summary['total'] += t
                    summary['code'] += c
                    summary['comment'] += cm
                    summary['blank'] += b
                except Exception as e:
                    print(f"Error processing {path}: {e}")
    return summary
if __name__ == "__main__":
    import sys
    target_dir = sys.argv[1] if len(sys.argv) > 1 else "."
    result = traverse_directory(target_dir)
    print(f"总计: {result['total']} 行")
    print(f"代码行: {result['code']} 行")
    print(f"注释行: {result['comment']} 行")
    print(f"空行: {result['blank']} 行")

运行方式python count_code_lines.py ./my_project


处理边缘情况:忽略注释与空行

上述Python脚本仅处理单行注释,实际项目中常见多行注释(如或),我们需要更智能的解析:

# 在count_lines_in_file中增加状态跟踪
in_multiline_comment = False
for line in f:
    stripped = line.strip()
    total_lines += 1
    # 处理多行注释开始
    if not in_multiline_comment and stripped.startswith('"""'):
        in_multiline_comment = True
        comment_lines += 1
        # 检查是否同一行结束
        if stripped.count('"""') == 2:
            in_multiline_comment = False
        continue
    if in_multiline_comment:
        comment_lines += 1
        if stripped.endswith('"""'):
            in_multiline_comment = False
        continue
    # 常规统计
    if not stripped:
        blank_lines += 1
    elif stripped.startswith('#'):
        comment_lines += 1
    else:
        code_lines += 1

类似地,C风格的注释也能通过匹配处理。


性能优化:处理大型代码库

当代码量超过10万行时,逐行读取可能变慢,优化策略:

  • 多线程处理:将文件列表分割到多个线程处理;
  • 跳过二进制文件:使用mimetypes库检测文件类型;
  • 缓存结果:对于不变的文件,使用MD5哈希检测并跳过重复统计;
  • 使用os.scandir()替代os.listdir():提升目录遍历效率。

示例:用concurrent.futures加速:

from concurrent.futures import ThreadPoolExecutor
def process_files_concurrently(file_list):
    with ThreadPoolExecutor(max_workers=8) as executor:
        futures = {executor.submit(count_lines_in_file, path): path for path in file_list}
        for future in futures:
            # 合并结果

常见问题问答(FAQ)

Q1:脚本统计的“代码行数”包含导入语句/定义吗?
A:是的,所有非空、非注释的有效Python代码都计入代码行,包括importdef等。

Q2:如何处理不同编程语言的注释风格?
A:建议为每种语言编写独立的注释识别模块,或者使用pygments词法解析库自动识别注释Token。

Q3:脚本能统计二进制文本文件(如PDF)吗?
A:不建议,在遍历目录时应按扩展名过滤,或尝试检测文件编码(UTF-8时跳过),避免解析乱码。

Q4:统计结果和IDE显示不一致?
A:IDE通常计算所有行(包括空行),因此差值可能来自注释/空行的处理标准不同,可在脚本中添加--ide-mode参数。

Q5:如何统计整组仓库的总行数?
A:扩展脚本接受多个根目录参数,或读取配置文件中的项目列表。

Q6:脚本能否自动生成报告?
A:可以,加入输出CSV或JSON的功能,甚至用matplotlib生成可视化图表。


最终建议:根据实际项目语言复杂度和规模,选择合适的脚本方案,对于简单的个人项目,Shell命令足够;对于大型多人协作项目,Python脚本结合Git钩子可实现自动化的行数趋势追踪。

抱歉,评论功能暂时关闭!