文章目录
- @staticmethod def count_lines(file_path: str) -> Dict[str, int]: “””智能统计代码行数””” try: with open(file_path, ‘r’, encoding=’utf-8′, errors=’ignore’) as f: lines = f.readlines() except Exception: return {‘total’: 0, ‘code’: 0, ‘comment’: 0, ‘blank’: 0} total_lines = len(lines) code_lines = 0 comment_lines = 0 blank_lines = 0 in_multiline_string = False multiline_quote = None for line in lines: stripped = line.strip() # 空行处理 if not stripped: blank_lines += 1 continue # 多行字符串处理 if in_multiline_string: if multiline_quote in stripped: quote_count = stripped.count(multiline_quote) if quote_count % 2 == 1: in_multiline_string = False multiline_quote = None comment_lines += 1 continue # 检查多行字符串开始 if ‘”””‘ in stripped or “”'” in stripped: # … 处理逻辑 # 单行注释 if stripped.startswith(‘#’): comment_lines += 1 continue # 代码行 code_lines += 1 return { ‘total’: total_lines, ‘code’: code_lines, ‘comment’: comment_lines, ‘blank’: blank_lines }
- class DropArea(QLabel): “””支持拖拽的区域””” files_dropped = pyqtSignal(list) def __init__(self): super().__init__() self.setAcceptDrops(True) self.setAlignment(Qt.AlignCenter) # 设置样式和提示文本 def dragEnterEvent(self, event: QDragEnterEvent): if event.mimeData().hasUrls(): event.acceptProposedAction() # 更新视觉反馈 def dropEvent(self, event: QDropEvent): files = [] for url in event.mimeData().urls(): file_path = url.toLocalFile() if os.path.exists(file_path): files.append(file_path) if files: self.files_dropped.emit(files)
- class CounterThread(QThread): “””后台统计线程””” progress_updated = pyqtSignal(int, int) file_processed = pyqtSignal(str, dict) directory_processed = pyqtSignal(str, dict) finished = pyqtSignal() def run(self): # 收集所有文件 all_files = [] for path in self.paths: if os.path.isfile(path) and path.endswith(‘.py’): all_files.append(path) elif os.path.isdir(path): py_files = self.counter.scan_directory(path) all_files.extend(py_files) # 逐个处理文件 for i, file_path in enumerate(all_files): stats = self.counter.count_lines(file_path) self.file_processed.emit(file_path, stats) self.progress_updated.emit(i + 1, len(all_files))
- 使用CSS样式表打造现代化界面: self.setStyleSheet(“”” QMainWindow { background-color: #f5f5f5; } QPushButton { background-color: #0078d4; color: white; border: none; padding: 8px 16px; border-radius: 4px; font-weight: bold; } QPushButton:hover { background-color: #106ebe; } “””)
- 使用QSplitter实现可调整的分割布局 自适应窗口大小 合理的组件间距和对齐
- 拖拽时的视觉反馈 进度条显示处理进度 清晰的状态提示 快捷键支持
目录
- 前言
- 项目背景
- 技术选型
- 为什么选择PyQt5
- 核心技术栈
- 功能设计
- 核心功能
- 完整效果图
- 核心代码实现
- 1. 代码行数统计算法
- 2. 拖拽功能实现
- 3. 多线程处理
- 界面设计亮点
- 1. 现代化样式
- 2. 响应式布局
- 3. 用户体验优化
- 项目特色
- 1. 智能识别算法
- 2. 性能优化
- 3. 用户友好
- 使用场景
- 1. 项目评估
- 2. 代码审查
- 3. 团队协作
- 安装和使用
- 环境要求
- 安装步骤
- 使用方法
- 技术难点与解决方案
- 1. 多行字符串识别
- 2. 编码问题
- 3. 性能优化
- 未来规划
- 短期目标
- 长期目标
- 总结
作为一名开发者,你是否经常需要统计项目中的代码行数?是否厌倦了使用命令行工具或者在线工具的繁琐操作?今天,我将分享如何使用PyQt5开发一款功能强大、界面美观的Python代码行数统计工具。
在日常开发中,我们经常需要:
- 统计项目的代码规模
- 分析代码质量(代码行vs注释行比例)
- 生成项目报告
- 快速了解项目结构
传统的解决方案往往存在以下问题:
- 命令行工具操作复杂
- 在线工具需要上传代码(安全隐患)
- 功能单一,缺乏可视化
- 不支持批量处理
因此,我决定开发一款集成度高、操作简便的图形化工具。
- 跨平台支持 – 一次开发,多平台运行
- 丰富的组件 – 提供完整的GUI组件库
- 成熟稳定 – 经过多年发展,稳定性极佳
- Python生态 – 与Python完美集成
- 现代化界面 – 支持样式表,可以打造美观界面
- GUI框架: PyQt5
- 多线程: QThread(避免界面卡顿)
- 文件处理: Python标准库
- 正则表达式: 智能识别注释和代码
1.拖拽支持
- 支持拖拽单个或多个.py文件
- 支持拖拽目录(自动递归扫描)
- 直观的拖拽区域设计
2.智能统计
- 准确识别代码行、注释行、空行
- 支持单行注释(#)
- 支持多行注释(“”"或’‘’)
- 正确处理行末注释
3.批量处理
- 多线程处理,避免界面卡顿
- 实时进度显示
- 支持大型项目扫描
4.结果展示
- 树形结构显示文件和目录
- 详细的统计信息
- 目录汇总功能
5.导出功能
- 支持导出统计结果
- 文本格式,便于分享

@staticmethod
def count_lines(file_path: str) -> Dict[str, int]:
"""智能统计代码行数"""
try:
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
lines = f.readlines()
except Exception:
return {'total': 0, 'code': 0, 'comment': 0, 'blank': 0}
total_lines = len(lines)
code_lines = 0
comment_lines = 0
blank_lines = 0
in_multiline_string = False
multiline_quote = None
for line in lines:
stripped = line.strip()
# 空行处理
if not stripped:
blank_lines += 1
continue
# 多行字符串处理
if in_multiline_string:
if multiline_quote in stripped:
quote_count = stripped.count(multiline_quote)
if quote_count % 2 == 1:
in_multiline_string = False
multiline_quote = None
comment_lines += 1
continue
# 检查多行字符串开始
if '"""' in stripped or "'''" in stripped:
# ... 处理逻辑
# 单行注释
if stripped.startswith('#'):
comment_lines += 1
continue
# 代码行
code_lines += 1
return {
'total': total_lines,
'code': code_lines,
'comment': comment_lines,
'blank': blank_lines
}
class DropArea(QLabel):
"""支持拖拽的区域"""
files_dropped = pyqtSignal(list)
def __init__(self):
super().__init__()
self.setAcceptDrops(True)
self.setAlignment(Qt.AlignCenter)
# 设置样式和提示文本
def dragEnterEvent(self, event: QDragEnterEvent):
if event.mimeData().hasUrls():
event.acceptProposedAction()
# 更新视觉反馈
def dropEvent(self, event: QDropEvent):
files = []
for url in event.mimeData().urls():
file_path = url.toLocalFile()
if os.path.exists(file_path):
files.append(file_path)
if files:
self.files_dropped.emit(files)
class CounterThread(QThread):
"""后台统计线程"""
progress_updated = pyqtSignal(int, int)
file_processed = pyqtSignal(str, dict)
directory_processed = pyqtSignal(str, dict)
finished = pyqtSignal()
def run(self):
# 收集所有文件
all_files = []
for path in self.paths:
if os.path.isfile(path) and path.endswith('.py'):
all_files.append(path)
elif os.path.isdir(path):
py_files = self.counter.scan_directory(path)
all_files.extend(py_files)
# 逐个处理文件
for i, file_path in enumerate(all_files):
stats = self.counter.count_lines(file_path)
self.file_processed.emit(file_path, stats)
self.progress_updated.emit(i + 1, len(all_files))
使用CSS样式表打造现代化界面:
self.setStyleSheet("""
QMainWindow {
background-color: #f5f5f5;
}
QPushButton {
background-color: #0078d4;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
font-weight: bold;
}
QPushButton:hover {
background-color: #106ebe;
}
""")
- 使用QSplitter实现可调整的分割布局
- 自适应窗口大小
- 合理的组件间距和对齐
- 拖拽时的视觉反馈
- 进度条显示处理进度
- 清晰的状态提示
- 快捷键支持
相比简单的行数统计,本工具能够:
- 正确识别Python的多行字符串
- 区分文档字符串和普通注释
- 处理复杂的注释嵌套情况
- 支持不同的引号格式
- 多线程处理,避免界面卡顿
- 内存优化,支持大型项目
- 异常处理,确保程序稳定性
- 编码自动检测,兼容性强
- 直观的拖拽操作
- 清晰的结果展示
- 完善的错误提示
- 详细的使用说明
快速了解项目规模
分析代码质量
生成项目报告
检查注释覆盖率
评估代码文档化程度
识别冗余代码
统一代码规范
制定开发计划
设定质量目标
- Python 3.6+
- PyQt5
# 1. 克隆项目
git clone [项目地址]
# 2. 安装依赖
pip install PyQt5
# 3. 运行程序
python code_counter.py
- 启动程序
- 拖拽文件或目录到拖拽区域
- 查看统计结果
- 导出报告(可选)
难点: Python的多行字符串可能跨越多行,需要正确识别开始和结束位置。
解决方案: 使用状态机模式,跟踪当前是否在多行字符串内部。
难点: Python文件可能使用不同的编码格式。
解决方案: 优先使用UTF-8,失败时使用errors='ignore’参数。
难点: 大型项目包含大量文件,可能导致界面卡顿。
解决方案: 使用QThread进行后台处理,通过信号更新界面。
- 支持更多编程语言
- 添加代码复杂度分析
- 支持自定义统计规则
- 集成版本控制系统
- 添加代码质量评分
- 支持团队协作功能
通过这个项目,我们成功打造了一款功能完整、界面美观的代码统计工具。项目展示了:
- PyQt5的强大功能 – 从基础组件到高级特性
- Python的实用性 – 快速原型开发到产品级应用
- 软件工程思维 – 需求分析、架构设计、用户体验
这不仅仅是一个工具,更是一次完整的软件开发实践。希望这个项目能够为你的开发工作带来便利,也希望能够启发你创造出更多有用的工具。
以上就是Python+PyQt5打造一个代码行数统计工具的详细内容,更多关于Python代码行数统计的资料请关注风君子博客其它相关文章!
您可能感兴趣的文章:
- Python+PyQt5设计实现一个C++源代码行数统计工具
- 使用Python编写词频统计工具的示例代码
- Python代码统计耗时的方法详解
- Python统计某列不同值的个数的示例代码
- Python中常用的统计检验代码分享
- 利用python实现词频统计分析的代码示例
- 使用Python统计代码运行时间的两种方法