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

Python操作OneDrive文件重命名报PermissionError[WinError32]

问题现象

运行Python文件加密脚本时触发Win32权限错误,加密逻辑本身可正常运行、生成加密后的文件,但执行原文件重命名操作时失败,报错信息如下:

<_io.TextIOWrapper name='C:/Users/depen/OneDrive/Documents/PNG_transparency_demonstration_1 >(2).png' mode='r' encoding='cp1252'>
read
encrypting
encrypted
encrypted file saved
Traceback (most recent call last):
  File "c:\Users\depen\OneDrive\Documents\python\timer\encrypt.py", line 93, in <module>
    encrypt(fpath)
  File "c:\Users\depen\OneDrive\Documents\python\timer\encrypt.py", line 67, in encrypt
    os.rename(file_fpath, file_fpath + ".encrypted")
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:/Users/depen/OneDrive/Documents/PNG_transparency_demonstration_1 (2).png' -> 'C:/Users/depen/OneDrive/Documents/PNG_transparency_demonstration_1 (2).png.encrypted'
根因分析

报错本质是文件句柄泄漏,原文件绝大多数情况是被当前Python进程自身占用,并非其他外部进程导致,问题出在代码逻辑本身:

  1. 分块读取原文件的外层with open把文件对象赋值给了变量f,但循环里写加密文件的内层with open又把新的文件对象赋值给了同一个变量f,直接覆盖了原文件的句柄引用。外层with块退出时找不到原文件的句柄,就没法正常关闭它,原文件一直被Python进程占用,后续不管是重命名还是删除都会触发占用报错。
  2. 在with上下文管理器内部手动调用f.close()、file.close()完全是多余操作,反而会干扰上下文管理器正常的句柄回收逻辑,进一步加剧句柄泄漏问题。
  3. 贴出的代码最后是os.remove(file_path),和报错栈里的os.rename逻辑不一致,说明实际运行的代码版本和贴出的版本有偏差,再加上文件存放在OneDrive同步目录,OneDrive同步进程、杀毒软件实时扫描也可能短暂占用文件,提升报错概率。
修复代码

直接按下面的逻辑调整即可,核心是避免变量名冲突、移除无效的手动close调用、减少不必要的文件操作:

fernet = AES(key)

def encrypt(file_path):
    start = time.time()
    encrypted_path = file_path + ".encrypted"

    def read_in_chunks(file_object, chunk_size=52428800):
        while True:
            data = file_object.read(chunk_size)
            if not data:
                break
            yield data

    # 读、写文件用不同变量名,彻底避免变量覆盖
    with open(file_path, "rb") as src_file:
        # 加密文件直接输出为最终带.encrypted后缀的文件,不用先写临时文件再改名
        with open(encrypted_path, "wb") as enc_file:
            for piece in read_in_chunks(src_file):
                encrypted_data = fernet.encrypt(randbytes(16), piece, randbytes(16))
                print(time.time() - start)
                enc_file.write(encrypted_data)
    # 出了with块,读写文件的句柄会被自动释放,不需要手动调用close

    # 记录原始文件名
    with open("filenames.txt", "a") as log_file:
        log_file.write(f"{file_path}\n")

    # 原文件删除/重命名前加简单重试,规避OneDrive、杀毒软件短暂占用
    retry_count = 3
    for i in range(retry_count):
        try:
            # 如果需要保留原文件仅加后缀,就把下面的os.remove换成os.rename逻辑
            os.remove(file_path)
            break
        except PermissionError:
            if i == retry_count - 1:
                raise
            time.sleep(0.5)

    cost = time.time() - start
    print(f"加密耗时: {cost} 秒")

关键调整说明

  • 读写文件分别用src_file、enc_file命名,从根源上避免变量覆盖导致的句柄泄漏
  • 把加密文件的打开操作移到循环外,不需要每写一块就打开关闭一次文件,大文件加密速度会明显提升
  • 删掉所有with块里多余的手动close调用,让上下文管理器自己处理句柄回收
  • 直接输出最终命名的加密文件,省去临时文件改名的步骤,减少文件操作触发占用的节点
  • 加了3次重试逻辑,遇到后台进程短暂占用文件的场景,等待0.5秒再操作,基本能覆盖OneDrive同步、杀毒扫描的常见场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 07:09:16