
1. 项目背景与需求解析开学季对于幼儿园行政老师来说总是异常忙碌特别是需要为每个班级准备大量基础信息材料。去年我负责幼儿园开学资料准备时光是打印、分类、装袋就花了整整三天时间还经常出现班级材料混淆的情况。今年我决定用Python写个小工具把点名册、周计划表、挂牌、圆牌等材料按班级自动合并打包直接生成压缩包发给对应班主任。这个工具主要解决三个痛点避免人工操作导致的班级材料错配大幅减少重复性文件整理时间确保每个班主任只收到自己班级的完整资料包2. 技术方案设计2.1 文件组织结构设计首先需要规范原始文件的存放结构。我在服务器上建立了如下目录/开学资料/ ├── 原始文件/ │ ├── 点名册/ │ │ ├── 小一班.xlsx │ │ ├── 小二班.xlsx │ │ └── ... │ ├── 周计划表/ │ │ ├── 小一班.docx │ │ ├── 小二班.docx │ │ └── ... │ ├── 挂牌模板.pptx │ ├── 圆牌模板.pptx │ └── 幼儿信息.csv └── 输出结果/2.2 关键技术实现2.2.1 班级信息提取从园园通系统导出的幼儿信息CSV包含所有班级数据需要先按班级拆分import pandas as pd def split_by_class(csv_path): df pd.read_csv(csv_path) class_groups df.groupby(班级) class_data {} for class_name, group in class_groups: class_data[class_name] group return class_data2.2.2 模板文件处理挂牌和圆牌使用统一的PPT模板需要根据班级信息动态生成from pptx import Presentation def generate_name_tag(template_path, class_name, output_path): prs Presentation(template_path) # 第一页是挂牌 slide prs.slides[0] for shape in slide.shapes: if shape.has_text_frame and 班级名称 in shape.text: shape.text shape.text.replace(班级名称, class_name) # 第二页是圆牌 slide prs.slides[1] # ...类似处理... prs.save(output_path)2.2.3 文件打包分发使用zipfile模块创建按班级分类的压缩包import zipfile import os def create_class_package(class_name, files_dict, output_dir): zip_path os.path.join(output_dir, f{class_name}_开学资料包.zip) with zipfile.ZipFile(zip_path, w) as zipf: for file_type, file_path in files_dict.items(): arcname f{class_name}_{file_type}{os.path.splitext(file_path)[1]} zipf.write(file_path, arcname) return zip_path3. 完整实现流程3.1 准备工作安装依赖库pip install pandas python-pptx openpyxl准备模板文件挂牌模板.pptx包含可替换的占位文本圆牌模板.pptx同上周计划表模板.docx各班级通用模板3.2 主程序逻辑import shutil from pathlib import Path def main(): base_dir Path(/开学资料) raw_dir base_dir / 原始文件 output_dir base_dir / 输出结果 # 清空输出目录 shutil.rmtree(output_dir, ignore_errorsTrue) output_dir.mkdir(exist_okTrue) # 按班级处理幼儿信息 class_data split_by_class(raw_dir / 幼儿信息.csv) for class_name, students_df in class_data.items(): # 生成班级专属文件 class_files {} # 处理点名册 roster_path raw_dir / 点名册 / f{class_name}.xlsx class_files[点名册] roster_path # 处理周计划表 plan_path raw_dir / 周计划表 / f{class_name}.docx class_files[周计划表] plan_path # 生成挂牌和圆牌 name_tag_path output_dir / f{class_name}_挂牌.pptx generate_name_tag(raw_dir / 挂牌模板.pptx, class_name, name_tag_path) class_files[挂牌] name_tag_path # 打包班级资料 create_class_package(class_name, class_files, output_dir) if __name__ __main__: main()4. 实际应用中的优化点4.1 性能优化当处理大规模幼儿园如超过20个班级时可以做以下优化使用多线程处理from concurrent.futures import ThreadPoolExecutor def process_class(class_name, students_df): # 封装单个班级的处理逻辑 ... with ThreadPoolExecutor(max_workers4) as executor: futures [] for class_name, students_df in class_data.items(): futures.append(executor.submit(process_class, class_name, students_df)) for future in futures: future.result()4.2 错误处理增加健壮性检查def safe_generate_name_tag(template_path, class_name, output_path): try: if not os.path.exists(template_path): raise FileNotFoundError(f模板文件不存在: {template_path}) generate_name_tag(template_path, class_name, output_path) return True except Exception as e: print(f生成{class_name}挂牌失败: {str(e)}) return False4.3 日志记录添加详细日志方便排查问题import logging logging.basicConfig( filename开学资料处理.log, levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s ) logging.info(f开始处理班级: {class_name}) try: # 处理逻辑 logging.info(f成功处理班级: {class_name}) except Exception as e: logging.error(f处理班级{class_name}出错: {str(e)})5. 实际部署注意事项文件权限问题确保程序对原始文件和输出目录有读写权限在Linux服务器上运行时注意用户组权限路径兼容性使用Path对象代替字符串路径如上面的示例处理Windows和Linux路径分隔符差异内存管理处理大型Excel文件时使用chunksize参数分块读取及时关闭文件句柄版本控制模板文件变更时更新版本号在压缩包名称中包含生成日期6. 扩展功能6.1 邮件自动发送集成邮件发送功能直接发送给班主任import smtplib from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders def send_to_teacher(email, attachment_path): msg MIMEMultipart() msg[Subject] f{os.path.basename(attachment_path)} - 开学资料 msg[From] adminkindergarten.com msg[To] email part MIMEBase(application, octet-stream) with open(attachment_path, rb) as file: part.set_payload(file.read()) encoders.encode_base64(part) part.add_header(Content-Disposition, attachment; filename{}.format(os.path.basename(attachment_path))) msg.attach(part) with smtplib.SMTP(smtp.server.com) as server: server.send_message(msg)6.2 生成进度报告在流程结束后生成处理报告def generate_report(output_dir, class_count, error_list): report_path output_dir / 处理报告.txt with open(report_path, w) as f: f.write(f开学资料处理报告\n) f.write(f生成时间: {datetime.now()}\n) f.write(f成功处理班级数: {class_count - len(error_list)}\n) f.write(f失败班级数: {len(error_list)}\n) if error_list: f.write(\n失败详情:\n) for class_name, error in error_list: f.write(f{class_name}: {error}\n)7. 常见问题解决中文乱码问题在文件开头添加编码声明# -*- coding: utf-8 -*-读取CSV时指定编码pd.read_csv(..., encodingutf-8-sig)文件被占用无法删除确保所有文件句柄都已关闭使用try-finally块保证资源释放模板文件被意外修改处理前先复制模板到临时目录使用版本控制管理模板文件内存不足处理大文件使用pd.read_csv(..., chunksize1000)分块读取考虑使用Dask等库处理超大数据这个工具在我们幼儿园实际使用后原本需要3天的手工工作现在20分钟就能完成而且完全避免了人为错误。班主任们反馈收到的资料包完整规范再也不会出现漏发错发的情况了。