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

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)

关键修复点

  1. 移除手动关闭操作:with fitz.open()会在代码块结束时自动释放文档资源,彻底避免重复关闭引发的错误。
  2. 修正PDF遍历逻辑:原代码中for line in doc是错误用法,fitz的doc对象是页面的迭代器,需遍历page后再提取整页文本处理。
  3. 优化循环退出流程:找到匹配内容后,逐层跳出页面循环和关键词循环,直接进入下一个文件的处理,避免无效操作。
  4. 解决文件占用问题:with块确保文档在移动前已完全关闭,消除Windows权限错误32的根源。

额外提示

如果仍遇到权限问题,可以临时关闭PyCharm的自动文件索引功能,避免后台进程占用待处理文件。

内容的提问来源于stack exchange,提问作者Addem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:55:17