《手把手教你写一个代码统计脚本:从入门到实战》
目录导读
- 为什么要写代码统计脚本?
- 代码统计脚本的核心功能拆解
- 三种主流实现方式对比(Bash / Python / Node.js)
- 实战:用Python写一个生产级代码统计器
- 常见问题与优化技巧
- 总结与扩展
为什么要写代码统计脚本?
很多开发者在项目交付、技术分享或团队管理中,需要快速了解项目的代码规模:总行数、文件数、注释占比、语言分布等,手动统计不仅低效,而且容易出错,编写一个自动化代码统计脚本成为刚需。

问答环节
问:统计代码行数的脚本一般用在什么场景?
答:常见场景包括:
- 项目开发进度汇报(量化工作成果)
- 开源项目筛选(评估复杂度)
- 代码审查前的预检(识别冗余文件)
- 个人技术博客的数据支撑
代码统计脚本的核心功能拆解
一个合格的代码统计脚本应包含以下能力:
- 递归遍历目录:自动扫描所有子文件夹
- 按文件扩展名过滤:只统计
.py、.js、.ts、.java等指定后缀 - 区分有效代码与注释:支持单行/多行注释及空行排除
- 统计维度:总行数、代码行、注释行、空行、文件数
- 输出格式化:控制台表格或导出为JSON/CSV
进阶功能(可选):
- 排除
.git、node_modules、dist等目录 - 按语言分组统计
- 可视化图表生成
三种主流实现方式对比
| 语言 | 优势 | 劣势 | 适合场景 |
|---|---|---|---|
| Bash | 极简,一行命令 | 功能单一,不支持复杂规则 | 快速估算,Linux环境 |
| Python | 生态丰富,易扩展 | 需安装环境 | 跨平台,定制化需求 |
| Node.js | 前端友好,npm包多 | 处理大文件时内存压力 | Web项目开发者 |
推荐:对于大多数开发者,Python是平衡易用性与性能的最佳选择。
实战:用Python写一个生产级代码统计器
步骤1:设计函数架构
import os
import re
from collections import defaultdict
def count_lines_in_file(file_path):
"""统计单个文件的有效代码、注释、空行"""
code_lines = 0
comment_lines = 0
blank_lines = 0
in_block_comment = False # 用于跟踪多行注释
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
for line in f:
stripped = line.strip()
# 空行
if not stripped:
blank_lines += 1
continue
# 多行注释结束
if in_block_comment:
comment_lines += 1
if '*/' in stripped or '"""' in stripped or "'''" in stripped:
in_block_comment = False
continue
# 单行注释
if stripped.startswith('#') or stripped.startswith('//'):
comment_lines += 1
continue
# 多行注释开始
if (stripped.startswith('/*') or
stripped.startswith('"""') or
stripped.startswith("'''")):
comment_lines += 1
if '*/' not in stripped and stripped.count('"""') < 2 and stripped.count("'''") < 2:
in_block_comment = True
continue
code_lines += 1
return code_lines, comment_lines, blank_lines
步骤2:遍历目录并聚合结果
def scan_directory(root_dir, extensions=None, exclude_dirs=None):
"""扫描目录,按扩展名过滤,排除指定文件夹"""
if extensions is None:
extensions = {'.py', '.js', '.ts', '.java', '.c', '.cpp', '.cs', '.go'}
if exclude_dirs is None:
exclude_dirs = {'.git', 'node_modules', 'dist', 'build', '__pycache__', 'venv'}
stats = defaultdict(lambda: {'files': 0, 'code': 0, 'comment': 0, 'blank': 0})
for root, dirs, files in os.walk(root_dir):
# 排除指定目录
dirs[:] = [d for d in dirs if d not in exclude_dirs]
for file in files:
ext = os.path.splitext(file)[1].lower()
if ext not in extensions:
continue
file_path = os.path.join(root, file)
try:
code, comment, blank = count_lines_in_file(file_path)
stats[ext]['files'] += 1
stats[ext]['code'] += code
stats[ext]['comment'] += comment
stats[ext]['blank'] += blank
except Exception as e:
print(f"跳过文件 {file_path}: {e}")
return stats
步骤3:漂亮地输出结果
def print_stats(stats):
"""格式化输出统计结果"""
print(f"\n{'语言':<12} {'文件数':<8} {'代码行':<10} {'注释行':<10} {'空行':<10} {'总行数':<10}")
print("-" * 60)
total_files = total_code = total_comment = total_blank = 0
for ext, data in sorted(stats.items()):
total_lines = data['code'] + data['comment'] + data['blank']
lang_name = ext.lstrip('.').upper() if ext else 'UNKNOWN'
print(f"{lang_name:<12} {data['files']:<8} {data['code']:<10} {data['comment']:<10} {data['blank']:<10} {total_lines:<10}")
total_files += data['files']
total_code += data['code']
total_comment += data['comment']
total_blank += data['blank']
print("-" * 60)
grand_total = total_code + total_comment + total_blank
print(f"{'总计':<12} {total_files:<8} {total_code:<10} {total_comment:<10} {total_blank:<10} {grand_total:<10}")
if __name__ == '__main__':
target_dir = input("请输入要统计的目录路径(默认当前目录): ") or '.'
stats = scan_directory(target_dir)
print_stats(stats)
常见问题与优化技巧
问答环节
问:如何处理大型项目(如超过100万行代码)时的性能问题?
答:
- 使用
os.walk而非递归遍历,减少内存占用 - 对文件采用逐行读取(
for line in f),避免一次性加载到内存 - 开启多线程/多进程(
concurrent.futures)加速文件扫描
问:脚本统计的代码行数与IDE显示不一致怎么办?
答:
- 检查换行符(Windows的
\r\nvs Linux的\n) - 确认是否过滤了生成代码(如编译后的
.js.map文件) - 统一注释判断规则(内联注释
code # comment是否计入代码行)
优化建议:
- 添加
--verbose参数显示每个文件的详细统计 - 支持
--ignore忽略特定文件模式(如*.min.js) - 集成
cloc(Count Lines of Code)作为备用引擎
总结与扩展
通过本文,你已经掌握从零编写一个健壮的代码统计脚本的方法,核心要点包括:
- 明确需求:界定哪些行算代码、注释、空行
- 分层设计:文件级统计 → 目录聚合 → 输出展示
- 防御性编码:处理编码错误、排除干扰目录
扩展方向:
- 结合Git历史,统计不同版本的代码增量
- 生成饼图展示语言分布(使用
matplotlib) - 做成命令行工具发布到PyPI,方便团队复用
如果你想直接使用现成的轮子,可以参考开源工具 cloc(Perl编写)或 scc(Go编写),但自己动手写一遍能让你对代码结构有更深的理解。
附加资源
- GitHub上搜索“code-line-counter”查看数百个实现参考
- 相关技术博客:探索者日记、脚本之家(原链接已替换为通用名称)
- 测试案例:下载一个中小型开源项目(如Flask)来验证你的脚本
打开你的编辑器,开始写第一个 line_counter.py 吧!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播