如何在Python中安全地使用文件系统作为一种共享内存?



TLDR:脚本A创建一个目录并在其中写入文件。脚本B定期检查该目录。脚本B如何知道脚本A何时完成写入,以便它可以访问文件?

我有一个Python脚本(称为渲染服务器),它接收生成图像和相关数据的请求。我需要运行一个单独的Python应用程序(称之为消费者)来使用这些数据。消费者不知道什么时候会有新的数据可用。理想情况下,它不需要知道脚本A的存在,只需要知道数据以某种方式可用。

我的快速而肮脏的解决方案是拥有两个Python脚本都知道的outputs目录。在该目录中,呈现服务器创建带有时间戳的目录,并在这些目录中保存几个文件。

渲染服务器做如下事情:

os.makedirs('outputs/' + timestamped_subdir)
# Write files into that directory.

消费者检查目录,类似于:

dirs = set()
while True:
new_dirs = set(glob('outputs/*')).difference(dirs)
if not len(new_dirs):
continue
# Do stuff with the contents of the latest new directory.

问题在于,在呈现服务器完成写入之前,消费者检查了目录的内容(这在FileNotFoundError中很明显)。我试图通过使渲染服务器这样做来解决这个问题:

os.makedisr('temp')
# Write files into that directory.
shutil.copytree('temp', 'outputs/' + timestamped_subdir)

但是消费者仍然能够知道timestamped_subdir的存在,在里面的文件被复制之前(又有一个FileNotFoundError)。什么是"正确"?怎么做我想要达到的目标?

注意:在写这篇文章的时候,我意识到我应该做shutil.move而不是shutil.copytree,这似乎已经修复了它。但我仍然不确定该操作的潜在机制,以确定它是否正确工作。

通过文件系统处理通信的一种常用方法是依赖于文件或文件夹的原子重命名或链接。

改变你的"渲染服务器"写入名为

的文件夹
outputs/' + timestamped_subdir + '_temp/' 

当"渲染服务器"这个目录已经完成了,把它改成

os.rename('outputs/' + timestamped_subdir + '_temp',  'outputs/' + timestamped_subdir)

只要所有文件都位于同一个文件系统中,那么重命名将是原子的。

现在你的其他进程只需要忽略以_temp结尾的目录,当它看到另一个文件夹时,它会知道这些目录已经完成了。

相关内容

最新更新