Files
hzdyjs/学校历史数据迁移/compare_student_headers.py
T
2025-12-23 22:25:02 +08:00

112 lines
3.4 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
比较两个学生 Excel 文件的表头(列名)。
用法:
python compare_student_headers.py \
--file-a 学校历史数据迁移/student1222.xls \
--file-b 学校历史数据迁移/student1127.xls
脚本会打印:
- 是否完全相同(顺序及名称)
- 仅在 A 中存在的列
- 仅在 B 中存在的列
- 顺序不同但内容相同的列(名称相同但位置不同)
"""
from __future__ import annotations
import os
import sys
import argparse
from typing import List
import pandas as pd
def read_headers(path: str) -> List[str]:
if not os.path.exists(path):
raise FileNotFoundError(path)
ext = os.path.splitext(path)[1].lower()
if ext == ".xls":
df = pd.read_excel(path, nrows=0, engine="xlrd")
else:
# .xlsx or others
df = pd.read_excel(path, nrows=0, engine="openpyxl")
return [str(c).strip() for c in list(df.columns)]
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--file-a", type=str, required=True)
parser.add_argument("--file-b", type=str, required=True)
args = parser.parse_args()
try:
headers_a = read_headers(args.file_a)
except Exception as e:
print(f"读取 {args.file_a} 表头失败: {e}")
sys.exit(2)
try:
headers_b = read_headers(args.file_b)
except Exception as e:
print(f"读取 {args.file_b} 表头失败: {e}")
sys.exit(2)
print(f"{args.file_a} 列数: {len(headers_a)}")
print(f"{args.file_b} 列数: {len(headers_b)}")
if headers_a == headers_b:
print("表头完全相同(顺序及名称一致)。")
return
set_a = set(headers_a)
set_b = set(headers_b)
only_a = sorted(list(set_a - set_b))
only_b = sorted(list(set_b - set_a))
if not only_a and not only_b:
print("列集合相同,但顺序不同。")
# show first few mismatches by position
diffs = []
for i, (ca, cb) in enumerate(zip(headers_a, headers_b)):
if ca != cb:
diffs.append((i + 1, ca, cb))
if diffs:
print("位置不一致的前若干列(位置, A列名, B列名):")
for d in diffs[:20]:
print(f" {d[0]:>3}: {d[1]} | {d[2]}")
else:
# maybe lengths differ; list remainder
if len(headers_a) != len(headers_b):
print("两表长度不同,下面列出多余部分:")
if len(headers_a) > len(headers_b):
print("A 多余:", headers_a[len(headers_b):len(headers_b)+20])
else:
print("B 多余:", headers_b[len(headers_a):len(headers_a)+20])
return
# print differences
if only_a:
print(f"仅在 A 中存在的列 ({len(only_a)}):")
for c in only_a[:100]:
print(" -", c)
if only_b:
print(f"仅在 B 中存在的列 ({len(only_b)}):")
for c in only_b[:100]:
print(" -", c)
# also list positional mismatches up to 20
diffs = []
for i in range(min(len(headers_a), len(headers_b))):
if headers_a[i] != headers_b[i]:
diffs.append((i + 1, headers_a[i], headers_b[i]))
if diffs:
print("位置不一致的前若干列(位置, A列名, B列名):")
for d in diffs[:20]:
print(f" {d[0]:>3}: {d[1]} | {d[2]}")
if __name__ == "__main__":
main()