Python PDF合并工具二次运行触发KeyError: '/Page'问题求助
问题根源与修复方案
首先,这个错误不是Tkinter的问题,而是你复用了同一个PdfFileMerger实例导致的!你在全局作用域创建了merger = PdfFileMerger(),第一次合并后这个实例已经存储了之前PDF的页面和书签数据,第二次点击按钮时再调用append(),PyPDF2会尝试处理旧的书签引用,从而抛出KeyError: '/Page'。
另外你的代码还有几个潜在问题:
- 检查Folder B文件存在的逻辑有误:当前代码只检查Folder B文件夹是否存在,但如果文件夹存在但没有对应
08_前缀的文件,filtered_entries[0]会触发索引越界错误。 - 每次点击按钮都会创建新的Label,导致界面堆积大量提示信息。
- 硬编码的文件路径不利于后续修改。
- 没有检查Folder A的三个PDF文件是否存在,可能触发文件找不到的异常。
修复后的完整代码
from tkinter import * from PyPDF2 import PdfFileMerger import os root = Tk() root.title("PDF Merger Tool") # 定义固定路径变量,方便后续修改 BASE_PATH = "C:\\Users\\User\\Desktop\\PDF" FOLDER_A = os.path.join(BASE_PATH, "Folder A") FOLDER_B = os.path.join(BASE_PATH, "Folder B") OUTPUT_PATH = os.path.join(BASE_PATH, "output") # 创建输出目录(如果不存在) os.makedirs(OUTPUT_PATH, exist_ok=True) # 创建UI组件 MainLabel = Label(root, text="PDF Rawat Jalan") MainLabel.pack(pady=10) KodeLabel = Label(root, text="Masukan Kode") KodeLabel.pack() kode = Entry(root, bg="gray") kode.pack(pady=5) # 固定的提示标签,避免重复创建 status_label = Label(root, text="") status_label.pack(pady=10) # Merge按钮的处理函数 def mergerclick(event=""): kode1 = kode.get().strip() if not kode1: status_label.config(text="请输入有效的Kode!") return # 每次合并都创建新的PdfFileMerger实例 merger = PdfFileMerger() success = True message = "" # 处理Folder A的三个文件 try: for prefix in ["1_", "2_", "3_"]: pdf_path = os.path.join(FOLDER_A, f"{prefix}{kode1}.pdf") if not os.path.exists(pdf_path): raise FileNotFoundError(f"找不到文件: {pdf_path}") merger.append(pdf_path) except Exception as e: status_label.config(text=f"合并失败: {str(e)}") return # 处理Folder B的08_前缀文件(可选) file8_found = False if os.path.exists(FOLDER_B): filtered_entries = [f for f in os.listdir(FOLDER_B) if f.startswith(f"08_{kode1}") and f.endswith(".pdf")] if filtered_entries: pdf8_path = os.path.join(FOLDER_B, filtered_entries[0]) merger.append(pdf8_path) file8_found = True # 写入输出文件 try: output_file = os.path.join(OUTPUT_PATH, f"{kode1}.pdf") merger.write(output_file) merger.close() # 记得关闭merger释放资源 if file8_found: message = f"{kode1} 已成功合并(包含08_文件)" else: message = f"未找到08_前缀文件,但{kode1}已成功合并" status_label.config(text=message) except Exception as e: status_label.config(text=f"写入文件失败: {str(e)}") success = False finally: merger.close() # 确保无论成功失败都关闭merger # 绑定回车键和按钮 root.bind("<Return>", mergerclick) mergerButton = Button(root, text="Merge", command=mergerclick) mergerButton.pack(pady=5) root.mainloop()
关键修复点说明
- 每次创建新的PdfFileMerger实例:在
mergerclick函数内部创建merger,确保每次合并都是全新的实例,避免旧数据干扰。 - 完善文件存在性检查:不仅检查Folder B是否存在,还检查对应前缀的PDF文件是否存在,避免索引越界。
- 固定状态提示标签:用
config()更新同一个Label的文本,避免界面堆积。 - 路径模块化:用
os.path.join拼接路径,同时将基础路径定义为变量,方便后续修改。 - 异常处理:增加了文件不存在和写入失败的异常捕获,让错误提示更友好。
- 关闭merger资源:合并完成后调用
merger.close(),释放文件资源。
内容的提问来源于stack exchange,提问作者Esi
相关产品推荐
相关产品推荐

