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

shutil.move报错文件夹被占用但文件均成功转移的排查咨询

问题排查与解决方法

1. 确认占用进程

  • 直接通过Windows自带工具实锤占用来源:按下Win+R输入resmon打开资源监视器,切换到「CPU」标签,在「关联的句柄」搜索框输入报错的文件夹路径C:\Users\Ze\PycharmProjects\Ploutos\ProductList\Unedited\1005001769427465\Images,即可看到持有句柄的进程,确认是否为Pycharm的索引进程(通常为pycharm64.exe或对应的索引子进程)。
  • 如果确认是Pycharm索引导致的占用,将ProductList目录加入Pycharm排除列表即可解决:打开设置>项目>项目结构,找到对应目录右键标记为「排除」,Pycharm将不再对该目录做实时索引,也就不会持有文件夹句柄。

2. 排查代码自身的隐性占用

你提到已卸载所有资源,大概率存在遗漏的资源持有场景:

  • 检查所有操作过Images目录下文件的代码,是否存在open()打开文件后未手动关闭、PIL/OpenCV等图片处理库操作完文件后未正确释放资源的情况,哪怕是只读模式打开文件也会触发占用锁,建议所有文件操作都使用with上下文管理器,自动释放句柄避免遗漏。
  • 检查是否有代码将当前工作目录切换到了待移动的子目录下未切回,进程的当前工作目录本身也会触发占用锁。

3. 偶发占用的兼容方案

如果是Pycharm索引、Windows Defender扫描这类第三方进程的临时占用,加重试机制即可解决绝大多数偶发报错,同时优化路径拼接逻辑避免手动写反斜杠的兼容问题:

import time
import shutil
import os

def move_product_to_edited(product_id, max_retries=3, retry_interval=1):
    global products_edited_during_session_counter

    unedited_products_path = os.path.join(application_path, 'ProductList', 'Unedited')
    edited_products_path = os.path.join(application_path, 'ProductList', 'Edited')
    src_path = os.path.join(unedited_products_path, str(product_id))
    dst_path = os.path.join(edited_products_path, str(product_id))

    if not os.path.exists(src_path):
        return
    
    for retry in range(max_retries):
        try:
            shutil.move(src_path, dst_path)
            break
        except PermissionError:
            if retry == max_retries - 1:
                # 重试耗尽后再抛出错误
                raise
            time.sleep(retry_interval)

4. 进阶排查方案

如果上述方法都未定位到问题:

  • 使用Process Explorer工具的查找句柄功能,比系统自带资源监视器展示的信息更详细,可以定位到具体持有句柄的线程,甚至对应调用栈。
  • 可以在执行shutil.move前加1秒延迟测试,如果加延迟后不再报错,基本可以确定是第三方进程的临时占用,直接用重试方案即可无需额外排查。

内容的提问来源于stack exchange,提问作者José Guedes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 11:54:05