Python脚本移动PDF时遇shutil权限错误及fitz文档关闭异常
问题修复方案
核心问题分析
你的代码存在两个关键问题导致报错:
- 重复关闭文档:同时使用
with上下文管理器(会自动关闭文档)和手动调用doc.close()/fitz.close(doc),导致文档被多次关闭,触发ValueError: document closed。 - 循环退出逻辑错误:找到匹配内容后直接关闭文档并break,但外层循环仍会尝试访问已关闭的文档,引发异常。
修复后的代码
import os import re import shutil import fitz # 请替换为实际路径和搜索词 origin_directory = "你的源文件夹路径" holding_Directory = "你的待处理文件夹路径" invoice_no_search_terms = ["发票号", "Invoice No."] invoice_numbers = [] # 遍历源目录所有文件 for filename in os.listdir(origin_directory): file_path = os.path.join(origin_directory, filename) print('line 34 ' + f"File path: {file_path}") # 用with上下文管理器自动管理PDF文档生命周期,无需手动关闭 with fitz.open(file_path) as doc: print("line 42") found_Inv_no = False # 遍历PDF的每一页(注意:fitz的doc是页面迭代器,不是行迭代器) for page in doc: try: page_text = page.get_text("utf-8") except UnicodeDecodeError: print(f"Warning: 无法解码页面内容: {page}") continue # 检查每个搜索关键词 for term in invoice_no_search_terms: if term in page_text: # 提取关键词后的数字 match = re.findall(r"\d+", page_text[page_text.find(term):], re.IGNORECASE) invoice_numbers.extend(match) found_Inv_no = True print("line 58 - 找到发票号") # 找到后跳出所有循环,处理下一个文件 break if found_Inv_no: break # 未找到目标内容,移动文件到待处理目录 if not found_Inv_no: moved_name = f"moved {filename}" print(moved_name) new_file_path = os.path.join(holding_Directory, moved_name) print(f"移动文件: {file_path} -> {new_file_path}") # with块结束后文档已自动关闭,不会出现文件占用问题 shutil.move(file_path, new_file_path) print("移动完成") print(filename)
关键修复点
- 移除手动关闭操作:
with fitz.open()会在代码块结束时自动释放文档资源,彻底避免重复关闭引发的错误。 - 修正PDF遍历逻辑:原代码中
for line in doc是错误用法,fitz的doc对象是页面的迭代器,需遍历page后再提取整页文本处理。 - 优化循环退出流程:找到匹配内容后,逐层跳出页面循环和关键词循环,直接进入下一个文件的处理,避免无效操作。
- 解决文件占用问题:
with块确保文档在移动前已完全关闭,消除Windows权限错误32的根源。
额外提示
如果仍遇到权限问题,可以临时关闭PyCharm的自动文件索引功能,避免后台进程占用待处理文件。
内容的提问来源于stack exchange,提问作者Addem
相关产品推荐
相关产品推荐

