Windows下使用tempfile复制文件遇Errno 13权限拒绝问题求助
解决Windows下临时文件复制权限拒绝问题
这个问题我太熟了——完全是Windows和Linux文件系统锁机制的差异搞的鬼!你猜的方向没错,核心矛盾就是Windows的文件锁定规则和NamedTemporaryFile默认行为的冲突。
问题根源
在Windows中,当一个文件处于打开的写入状态时,系统会强制锁定它,阻止任何其他操作(哪怕是同一个进程里的复制)访问该文件;而Linux允许这种跨操作的文件访问。同时NamedTemporaryFile默认的delete=True参数会让文件在关闭时自动删除,这就陷入了「不关闭无法复制,关闭了文件就没了」的死循环。
解决方案:设置delete=False并手动清理临时文件
我们只需要给NamedTemporaryFile加上delete=False参数,让临时文件关闭后不会被自动删除,等完成复制操作后再手动删除它。下面是修正后的完整代码:
from pathlib import Path from shutil import copyfile from tempfile import NamedTemporaryFile import os sourcefile = Path("Path\\to\\source").resolve() insert_lineno = 2 insert_data = "# Mean magnitude = " + str(mean_mag)+"\n" # 关键改动1:添加delete=False,同时指定encoding避免跨系统乱码 with sourcefile.open(mode="r", encoding="utf-8") as source: destination = NamedTemporaryFile(mode="w", dir=str(sourcefile.parent), delete=False, encoding="utf-8") lineno = 1 while lineno < insert_lineno: line = source.readline() destination.write(line) lineno += 1 destination.write(insert_data) # 按块写入剩余内容,保持原代码的性能优势 while True: data = source.read(1024) if not data: break destination.write(data) destination.flush() # 关键改动2:先关闭临时文件,解除Windows的文件锁定 destination.close() # 现在可以安全执行复制了 copyfile(destination.name, str(sourcefile)) # 关键改动3:手动删除临时文件,避免残留垃圾 os.unlink(destination.name)
额外优化:添加异常处理确保临时文件被清理
为了避免复制过程中出错导致临时文件残留,建议加上try...finally块,确保无论操作成功还是失败,临时文件都会被删除:
from pathlib import Path from shutil import copyfile from tempfile import NamedTemporaryFile import os sourcefile = Path("Path\\to\\source").resolve() insert_lineno = 2 insert_data = "# Mean magnitude = " + str(mean_mag)+"\n" temp_file_path = None try: with sourcefile.open(mode="r", encoding="utf-8") as source: destination = NamedTemporaryFile(mode="w", dir=str(sourcefile.parent), delete=False, encoding="utf-8") temp_file_path = destination.name lineno = 1 while lineno < insert_lineno: line = source.readline() destination.write(line) lineno += 1 destination.write(insert_data) while True: data = source.read(1024) if not data: break destination.write(data) destination.flush() destination.close() copyfile(temp_file_path, str(sourcefile)) finally: # 无论成功失败,都清理临时文件 if temp_file_path and os.path.exists(temp_file_path): os.unlink(temp_file_path)
这样既解决了Windows的权限问题,又保留了批量处理文件的性能优势——不用频繁打开关闭原文件,通过临时文件一次性处理后覆盖即可。
内容的提问来源于stack exchange,提问作者AceTorterra1
相关产品推荐
相关产品推荐

