使用PyPDF2结合with循环触发ValueError,请求排查错误
问题分析与解决方案
你的代码触发ValueError的核心原因是PyPDF2的PdfReader依赖打开的文件句柄,而with块结束后文件会被自动关闭。writer.add_page()并没有立即把页面数据复制到writer内存中,只是保存了对reader.pages的引用。当后续执行writer.write()时,程序尝试访问已关闭的文件资源,就会抛出错误。
修正方案(两种可选)
方案一:将PDF文件读取到内存再处理(推荐)
通过把文件内容读取到内存中的BytesIO对象,让PdfReader不再依赖原文件句柄,即使文件关闭也能正常访问页面数据。
需要导入BytesIO,修改后的代码如下:
from io import BytesIO import glob import PyPDF2 def remove_last_page(): sorted_filenames = sorted(glob.glob('Reading*.pdf'), key=sort_key) writer = PyPDF2.PdfWriter() for file_path in sorted_filenames: with open(file_path, 'rb') as file: # 读取整个PDF内容到内存 pdf_content = file.read() # 基于内存中的内容创建PdfReader reader = PyPDF2.PdfReader(BytesIO(pdf_content)) # 添加除最后一页外的所有页面 page_count = len(reader.pages) if page_count > 1: for i in range(page_count - 1): writer.add_page(reader.pages[i]) new_filename = 'Combined_Readings.pdf' with open(new_filename, 'wb') as new_file: writer.write(new_file)
添加page_count > 1的判断是为了避免单个页面的PDF触发无意义的循环(虽然不会报错,但更严谨)。
方案二:确保文件句柄在写入前保持打开
如果不想修改内存读取的逻辑,可以把所有文件的打开操作放在同一个上下文里,但这种方式不适合大量PDF文件的场景(会占用多个文件句柄):
import glob import PyPDF2 def remove_last_page(): sorted_filenames = sorted(glob.glob('Reading*.pdf'), key=sort_key) writer = PyPDF2.PdfWriter() # 保存所有打开的文件对象,避免提前关闭 open_files = [] try: for file_path in sorted_filenames: f = open(file_path, 'rb') open_files.append(f) reader = PyPDF2.PdfReader(f) for i in range(len(reader.pages) - 1): writer.add_page(reader.pages[i]) new_filename = 'Combined_Readings.pdf' with open(new_filename, 'wb') as new_file: writer.write(new_file) finally: # 手动关闭所有文件 for f in open_files: f.close()
内容的提问来源于stack exchange,提问作者jolene
相关产品推荐
相关产品推荐

