比较两文件差异python实现
比较1比较2下面的是GUI方式俩栏颜色对比较适合前后有改动的同一文档import sysfrom difflib import SequenceMatcherfrom PySide6.QtCore import Qt, QRegularExpressionfrom PySide6.QtGui import (QFont, QColor, QSyntaxHighlighter, QTextCharFormat,QTextCursor, QTextDocument)from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,QHBoxLayout, QPlainTextEdit, QPushButton, QFileDialog,QLabel, QSplitter)# ---------- Diff 计算 ----------def compute_diff(a_lines, b_lines):返回 b_lines 的标注列表: (equal|add|del|change, line, a_idx)sm SequenceMatcher(None, a_lines, b_lines, autojunkFalse)result []for tag, i1, i2, j1, j2 in sm.get_opcodes():if tag equal:for k in range(j2 - j1):result.append((equal, b_lines[j1 k], i1 k))elif tag insert:for k in range(j1, j2):result.append((add, b_lines[k], None))elif tag delete:for k in range(i1, i2):result.append((del, a_lines[k], k))elif tag replace:for k in range(j1, j2):result.append((change, b_lines[k], None))for k in range(i1, i2):result.append((del, a_lines[k], k))return result# ---------- 高亮器 ----------COLORS {equal: QColor(#F5F5F5),add: QColor(#C8E6C9), # 浅绿del: QColor(#FFCDD2), # 浅红change: QColor(#FFF59D), # 浅黄}class DiffHighlighter(QSyntaxHighlighter):def __init__(self, doc, marks):super().__init__(doc)self.marks marks # list[bool] —— 长度等于行数def highlightBlock(self, text):block_num self.currentBlock().blockNumber()if block_num len(self.marks) and self.marks[block_num]:fmt QTextCharFormat()fmt.setBackground(QColor(#FFEB3B))fmt.setProperty(QTextCharFormat.Property.FullWidthSelection, True)self.setFormat(0, len(text), fmt)# ---------- 主窗口 ----------class DiffWindow(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle(Python Diff Viewer)self.resize(1200, 700)central QWidget(); self.setCentralWidget(central)v QVBoxLayout(central)# 顶部按钮栏bar QHBoxLayout()self.btn_left QPushButton( 打开左文件)self.btn_right QPushButton( 打开右文件)self.btn_diff QPushButton( 对比)for b in (self.btn_left, self.btn_right, self.btn_diff):bar.addWidget(b)bar.addStretch()v.addLayout(bar)# 左右文本框self.left QPlainTextEdit(); self.left.setFont(QFont(Consolas, 11))self.right QPlainTextEdit(); self.right.setFont(QFont(Consolas, 11))for ed in (self.left, self.right):ed.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap)splitter QSplitter(Qt.Orientation.Horizontal)splitter.addWidget(self._wrap(左文件 (原版本), self.left))splitter.addWidget(self._wrap(右文件 (新版本), self.right))splitter.setSizes([600, 600])v.addWidget(splitter)# 信号self.btn_left.clicked.connect(lambda: self._open(self.left))self.btn_right.clicked.connect(lambda: self._open(self.right))self.btn_diff.clicked.connect(self._run_diff)def _wrap(self, title, edit):w QWidget(); lay QVBoxLayout(w); lay.setContentsMargins(0,0,0,0)lay.addWidget(QLabel(title))lay.addWidget(edit)return wdef _open(self, editor):path, _ QFileDialog.getOpenFileName(self, 选择文件)if path:with open(path, r, encodingutf-8, errorsignore) as f:editor.setPlainText(f.read())def _run_diff(self):a self.left.toPlainText().splitlines()b self.right.toPlainText().splitlines()diff compute_diff(a, b)# --- 左文件按 a 的顺序仅显示 del/equal ---left_marks []left_lines []# 同步高亮把 b 的 add/change 也映射到 a 侧对应行a_highlight set() # 在 a 中需要高亮的行号与 b 的 add/change 对齐# 重新跑一遍以同步两侧位置sm SequenceMatcher(None, a, b, autojunkFalse)a_pos, b_pos 0, 0a_blocks, b_blocks [], []for tag, i1, i2, j1, j2 in sm.get_opcodes():if tag equal:for k in range(i2 - i1):a_blocks.append((equal, a[i1k], i1k))b_blocks.append((equal, b[j1k], j1k))elif tag insert:for k in range(j1, j2):a_blocks.append((pad, , i1))b_blocks.append((add, b[k], j1k))elif tag delete:for k in range(i1, i2):a_blocks.append((del, a[k], i1k))b_blocks.append((pad, , j1))elif tag replace:# 先用 a 行标 del再用 b 行标 add/changefor k in range(i1, i2):a_blocks.append((del, a[k], i1k))b_blocks.append((pad, , j1k))for k in range(j1, j2):a_blocks.append((pad, , i1k))b_blocks.append((change, b[k], j1k))# 渲染到文本框 上色self._render(self.left, a_blocks)self._render(self.right, b_blocks)def _render(self, editor, blocks):editor.setPlainText(\n.join(b[1] for b in blocks))cursor editor.textCursor()cursor.select(QTextCursor.SelectionType.Document)fmt_default QTextCharFormat(); fmt_default.setBackground(QColor(white))cursor.setCharFormat(fmt_default)cursor.clearSelection()for i, (tag, _, _) in enumerate(blocks):color COLORS.get(tag)if not color: continueblock editor.document().findBlockByNumber(i)hl QTextCursor(block)hl.movePosition(QTextCursor.MoveOperation.EndOfBlock,QTextCursor.MoveMode.KeepAnchor)fmt QTextCharFormat(); fmt.setBackground(color)hl.setCharFormat(fmt)editor.viewport().update()if __name__ __main__:app QApplication(sys.argv)w DiffWindow(); w.show()sys.exit(app.exec())但缺行号显示补充

相关新闻

cc-switch 教程:从手动改配置到一键切换 Claude Code API 供应商

cc-switch 教程:从手动改配置到一键切换 Claude Code API 供应商

这次我们来看一个 Claude Code 日常使用中非常实用的配套工具:cc-switch。如果你已经装了 Claude Code,还在手工改配置文件、来回切换 API 供应商或者账号配置,那这个工具就是针对这个痛点来的。这篇文章会讲清楚 cc-switch 是什么、为什么需…

2026/9/29 2:20:12 阅读更多 →
Jspreadsheet(jExcel v2)只读列与只读单元格实战:readOnly 配置与动态控制全解析

Jspreadsheet(jExcel v2)只读列与只读单元格实战:readOnly 配置与动态控制全解析

前端UI组件 【免费下载链接】ce Jspreadsheet is a lightweight JavaScript data grid component for creating interactive data grids with advanced spreadsheet controls. 项目地址: https://gitcode.com/gh_mirrors/ce/ce 点击查看 免费下载 导读 本文以官方…

2026/9/30 3:57:57 阅读更多 →
PPT Master:如何把一份文档变成原生可编辑的 PPT

PPT Master:如何把一份文档变成原生可编辑的 PPT

PPT Master:如何把一份文档变成原生可编辑的 PPT 【免费下载链接】ppt-master AI turns documents or topics into real, native PowerPoint decks—with native shapes, transitions and animations, data-backed charts and tables on demand, audio narration fr…

2026/9/30 3:16:33 阅读更多 →

最新新闻

AI古装大片实战:Image 2.5提示词与参数全解析

AI古装大片实战:Image 2.5提示词与参数全解析

1. 从“摄影师要失业”说起:AI古装大片到底怎么拍女朋友想拍古装大片,这个需求本身就带着几个硬性条件:场景要古风、服装要考究、光影要有电影感、出片速度还得快。传统流程走一遍——约摄影师、租汉服、找园林、等档期、后期修图&#xff0c…

2026/9/30 9:46:45 阅读更多 →
两级解耦:学习决策中路径选择与处理深度调度的架构设计与实践

两级解耦:学习决策中路径选择与处理深度调度的架构设计与实践

1. 学习决策的两级解耦:从路径选择到处理深度调度1.1 为什么“学什么”和“学多深”必须拆开看很多做学习系统或者自适应引擎的朋友都遇到过同一个困境:模型在决定下一步动作时,既要选方向,又要定力度,结果两个目标互相…

2026/9/30 9:46:45 阅读更多 →
Jev轻量AI工具:面向非专业用户的低门槛创作实践

Jev轻量AI工具:面向非专业用户的低门槛创作实践

1. 这不是又一个“全能AI”,而是一次对AI产品节奏的精准踩点最近朋友圈和科技社群里反复刷到“Jev”这个词,标题里那句“没那么强,但足够给有些乏味的AI圈带来新刺激”特别戳人——它没说“颠覆”“革命”“碾压”,反而用“没那么…

2026/9/30 9:46:45 阅读更多 →
C语言结构体:点号和箭头的本质区别与用法详解

C语言结构体:点号和箭头的本质区别与用法详解

有很多C语言新手在学到结构体的时候,会卡在“结构体变量用点,结构体指针用箭头”这个口诀上。但背口诀容易,真正遇到混用、嵌套、链表、函数传参的时候就容易懵:为什么有时候看到 s.name 能编译,有时候又必须要 p-&…

2026/9/30 9:46:45 阅读更多 →
TCPsocket编程从accept到线程池连接型服务器的第一课

TCPsocket编程从accept到线程池连接型服务器的第一课

TCP socket 编程:从 accept 到线程池,连接型服务器的第一课 我的github:(https://github.com/xcx55/ubuntu-linux-project) 感谢各位大佬参观我的github!! UDP 那条线走完后,8 月 30 号到 9 月 1 号进入了 …

2026/9/30 9:46:45 阅读更多 →
把Profiler塞进玩家真机:轻量级性能监控SDK设计与实践

把Profiler塞进玩家真机:轻量级性能监控SDK设计与实践

以前做移动游戏性能优化,最头疼的就是手里的 Profiler 只能在开发机上跑。办公室里数据漂漂亮亮,玩家反馈却永远是“卡顿”“发热”“玩一会儿就掉帧”,你连个像样的采样都拿不到。后来我们干脆换了个思路:既然拉不齐设备环境&…

2026/9/30 9:45:45 阅读更多 →

日新闻

Base64 图片头部特征识别:从文件头到格式判断的完整指南

Base64 图片头部特征识别:从文件头到格式判断的完整指南

1. 项目概述:为什么说看懂 base64 图片头部是基本功这几年跟 base64 打交道的机会越来越多,后端接口返回图片、前端渲染验证码、小程序里存小图、还有一些老系统导出报表,动不动就给你一段长到怀疑人生的 base64 字符串。很多人拿到字符串就直…

2026/9/30 0:00:35 阅读更多 →
Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

简介:本资源是一份面向Java初学者与课程设计学生的公交站牌广告灯箱管理系统毕业设计文档,聚焦城市公共广告资源信息化管理痛点,提供从需求分析到技术实现的完整方案。文档采用标准学术论文结构,含摘要、英文摘要、目录及五章正文…

2026/9/30 0:00:35 阅读更多 →
用 Redis Lua 构建大模型 API 多租户原子配额治理体系

用 Redis Lua 构建大模型 API 多租户原子配额治理体系

我去年年底接了一个内部 AI 平台的治理需求,背景很直接:公司把 DeepSeek、MiniMax 这类大模型 API 统一封装成内部网关,开放给几个业务团队用。结果第一个月账单出来,额度直接超了 4 倍。仔细查日志,发现原因并不复杂—…

2026/9/30 0:00:35 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 8:16:59 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 16:41:41 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/29 8:24:48 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/29 19:29:29 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/29 5:58:00 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/29 3:55:56 阅读更多 →