PyPDF2实现监控文件夹PDF合并至文档末尾而非开头的问题
问题:PyPDF2合并新增PDF到目标文件末尾失败,总是添加到开头
我是Python新手,无法找到正确方法让PyPDF2将监控文件夹中新增的PDF文件合并到目标文件(invoices.pdf)的末尾,而非开头。以下是我目前的代码:
import time import os import sys import logging from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler from PyPDF2 import PdfReader, PdfMerger class Watcher: DIRECTORY_TO_WATCH = "C:\\Users\\Grayden\\Desktop\\PDF_Trial" FILENAME = "invoices.pdf" def __init__(self): self.observer = Observer() def run(self): event_handler = Handler() self.observer.schedule(event_handler, self.DIRECTORY_TO_WATCH, recursive=True) self.observer.start() try: while True: time.sleep(5) except: self.observer.stop() print("Error") self.observer.join() class Handler(FileSystemEventHandler): @staticmethod def on_any_event(event): if event.is_directory: return None elif event.event_type == 'created': # Take any action here when a file is first created. if event.src_path.endswith(".pdf"): print("New PDF file added: %s" % event.src_path) merge_pdfs(Watcher.DIRECTORY_TO_WATCH, Watcher.FILENAME) def merge_pdfs(directory, output_filename): pdf_list = [] for foldername, subfolders, filenames in os.walk(directory): for filename in filenames: if filename.endswith('.pdf'): filepath = os.path.join(foldername, filename) pdf_list.append(filepath) pdf_merger = PdfMerger() for pdf_path in pdf_list: with open(pdf_path, 'rb') as pdf_file: pdf_reader = PdfReader(pdf_file, strict=False) pdf_merger.append(pdf_reader) with open(os.path.join(directory, output_filename), 'wb') as file: pdf_merger.write(file) if __name__ == '__main__': w = Watcher() w.run()
解决方案
你的问题核心在于原代码每次都会遍历文件夹中所有PDF重新合并,遍历顺序的不确定性导致新文件可能被加到开头。正确的做法是只将新添加的PDF追加到已有的目标文件末尾,而非重新合并全部文件。修改后的代码如下:
import time import os from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler from PyPDF2 import PdfReader, PdfMerger class Watcher: DIRECTORY_TO_WATCH = "C:\\Users\\Grayden\\Desktop\\PDF_Trial" FILENAME = "invoices.pdf" def __init__(self): self.observer = Observer() def run(self): event_handler = Handler() self.observer.schedule(event_handler, self.DIRECTORY_TO_WATCH, recursive=True) self.observer.start() try: while True: time.sleep(5) except KeyboardInterrupt: self.observer.stop() print("监控已停止") self.observer.join() class Handler(FileSystemEventHandler): @staticmethod def on_created(event): if event.is_directory: return None if event.src_path.endswith(".pdf"): # 等待1秒确保文件完全写入磁盘 time.sleep(1) print("New PDF file added: %s" % event.src_path) merge_pdfs(Watcher.DIRECTORY_TO_WATCH, Watcher.FILENAME, event.src_path) def merge_pdfs(directory, output_filename, new_pdf_path): output_path = os.path.join(directory, output_filename) # 跳过目标文件本身,避免循环处理 if os.path.basename(new_pdf_path) == output_filename: return pdf_merger = PdfMerger() # 先加载已存在的目标文件 if os.path.exists(output_path): with open(output_path, 'rb') as output_file: pdf_merger.append(PdfReader(output_file, strict=False)) # 追加新PDF到末尾 with open(new_pdf_path, 'rb') as new_pdf_file: pdf_merger.append(PdfReader(new_pdf_file, strict=False)) # 写入合并后的文件 with open(output_path, 'wb') as file: pdf_merger.write(file) if __name__ == '__main__': w = Watcher() w.run()
关键修改点
- 合并逻辑优化:不再遍历所有PDF,仅将新添加的单个文件追加到目标文件末尾
- 避免循环处理:判断如果触发事件的是目标文件
invoices.pdf,直接跳过 - 文件完整性保障:添加1秒延迟,确保新文件完全写入磁盘后再处理
- 异常处理完善:明确捕获
KeyboardInterrupt,让程序可以优雅停止
内容的提问来源于stack exchange,提问作者Gtwizzy
相关产品推荐
相关产品推荐

