返回

Python 子进程优雅读取临时文件的最佳实践

windows

在子进程中优雅地读取临时文件

在编程中,有时我们需要将数据存储在临时文件中,以便另一个进程可以访问它。在 Python 中,可以使用 NamedTemporaryFile 类创建临时文件。但是,在 Windows 上,如果临时文件在写入后被刷新但没有关闭,子进程将无法打开它进行读取。

解决方案:使用 mkstemp

一种更优雅的方法是使用 mkstemp 函数,它返回一个文件符和一个文件名。我们可以使用 os.fdopen() 函数将文件符包装在文件对象中,如下所示:

import tempfile

fd, temp_filename = tempfile.mkstemp()
with os.fdopen(fd, 'w') as f:
    f.write(someStuff)

# ...run the subprocess and wait for it to complete...

os.close(fd)
os.remove(temp_filename)

使用此方法,无需关闭文件即可将临时文件传递给子进程,从而简化了代码并避免了潜在的错误来源。此外,它在所有平台上都可靠地工作,而无需担心特定于操作系统的细微差别。

替代方案:使用 TemporaryDirectory 上下文管理器

另一个替代方案是使用 TemporaryDirectory 上下文管理器,它创建一个临时目录并在退出时自动删除该目录。我们可以将临时文件写入该目录,然后传递目录路径给子进程。

from tempfile import TemporaryDirectory

with TemporaryDirectory() as temp_dir:
    temp_file = os.path.join(temp_dir, 'temp_file')
    with open(temp_file, 'w') as f:
        f.write(someStuff)

# ...run the subprocess and wait for it to complete...

这种方法的优点是它不需要显式删除临时文件,因为它会在上下文管理器退出时自动删除。

常见问题解答

1. 为什么在 Windows 上刷新临时文件会导致问题?

在 Windows 上,当文件被刷新时,它的安全描述符会发生变化。这可能会阻止子进程访问该文件,即使它具有对父进程文件的访问权限。

2. 为什么 delete=False 不应该用于 NamedTemporaryFile

使用 delete=False 可能会导致资源泄漏,因为临时文件不会在进程退出时自动删除。此外,它可能会导致其他问题,例如,如果子进程在父进程删除文件之前打开了临时文件,则可能出现 race condition。

3. 除了上述方法外,还有其他方法可以解决这个问题吗?

可以使用其他方法,例如使用 fcntl.lockf() 函数显式锁定临时文件,以便子进程可以访问它。但是,这些方法可能更复杂,并且在不同平台上的行为可能不同。

4. 使用 mkstempTemporaryDirectory 上下文管理器的优缺点是什么?

使用 mkstemp 的优点是它在所有平台上都可靠地工作,并且不需要显式删除临时文件。使用 TemporaryDirectory 上下文管理器的优点是它自动删除临时目录,并且不需要显式关闭临时文件。

5. 如何使用这些方法传递文件路径给子进程?

可以使用 subprocess.Popen 函数或 multiprocessing.Process 类传递文件路径给子进程。具体方法取决于所使用的库和子进程的类型。