You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:51:15