无法在Windows上删除由`tempfile.mkstemp()`创建的文件

15

这是我的示例代码:

import os
from tempfile import mkstemp

fname = mkstemp(suffix='.txt', text=True)[1]
os.remove(fname)

当我在Linux上运行时,它正常工作。但是当我在Windows XP上使用Python 3.4.4运行它时,它会引发以下错误:

Traceback (most recent call last):
  File "C:\1.py", line 5, in <module>
    os.remove(fname)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\DOCUME~1\\IEUser\\LOCALS~1\\Temp\\tmp3qv6ppcf.txt'

然而,当我使用tempfile.NamedTemporaryFile()创建临时文件并关闭它时,它会自动删除。

为什么Windows无法删除使用mkstemp创建的文件?我错在哪里了?


你尝试过先关闭它吗? - Ignacio Vazquez-Abrams
@IgnacioVazquez-Abrams:啥?我哪里打开了它?mkstemp()不是只创建文件吗?我的代码中没有open(),而且fname是一个字符串对象。 - Remi Guan
3
注意,mkstemp() 返回一个含有已打开文件句柄的元组。在关闭该句柄之前,该文件一直被使用(......由另一个进程:您自己的进程)。它在Windows上运行是因为os.remove()的工作方式(_在Windows上,尝试删除正在使用的文件会引发异常;在Unix上,目录条目被删除,但分配给该文件的存储空间在原始文件不再使用之前不可用_)。 - Adriano Repetti
2
使用NamedTemporaryFile,Python使用WinAPI FILE_FLAG_DELETE_ON_CLOSE,它需要DELETE访问权限,并且文件是使用FILE_SHARE_DELETE共享打开的。这意味着您可以在其上调用os.remove而不会遇到共享冲突,但请注意,直到最后一个内核引用或句柄关闭之前,该文件实际上并未被删除。删除时关闭标志会导致文件系统将文件标记为要取消链接,但这只有在关闭最后一个引用时才会发生。现有句柄可以调用SetFileInformationByHandle来撤消删除处理。 - Eryk Sun
1
mkstemp 不使用 FILE_FLAG_DELETE_ON_CLOSE(通过 CRT 的 O_TEMPORARY 标志),因此它不会使用 DELETE 访问或 FILE_SHARE_DELETE 共享打开文件。当您尝试对其调用 os.remove 时,它会调用 WinAPI 的 DeleteFile,该函数尝试使用 DELETE 访问权限打开以设置删除处理方式,但由于您已经打开了该文件而没有共享删除权限,所以操作失败。 - Eryk Sun
显示剩余2条评论
1个回答

30

来自文档

以最安全的方式创建临时文件。[...]

[...]

mkstemp() 返回一个元组,其中包含打开文件的操作系统级句柄(与 os.open() 返回的相同)和该文件的绝对路径名,按照该顺序排列。

fd, fname = mkstemp(suffix='.txt', text=True)
os.close(fd)
os.remove(fname)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接